1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-04 00:15:45 +02:00

Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Gerkiz 2022-11-04 19:01:31 +01:00
commit db618b4db8
54 changed files with 2074 additions and 715 deletions

View File

@ -113,7 +113,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'

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.3.1-v1.3.5\n• Bugfixes.\n• Rebalancings, including: iron ore amounts buffed; kraken reward improved; final resource requirement increased; overall difficulty reduced.\n• Minor reordering of islands.\n• An officer will now be prioritised for the captain role if the captain disconnects.\n\nv1.3\n• Hold chests are now destructible.\n• Fluid is now transportable between decks.\n• New classes, and new 'Class Window'.\n• Other improvements, small features, and balance changes.\n\nv1.2\n• Mod portal release.
softmod_info_updates_2=v1.4.1\n• Cannon upgrade is now more expensive and appears less often.\n• Bugfixes.\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.\n\nv1.3.1-v1.3.5\n• Bugfixes.\n• Rebalancings, including: iron ore amounts buffed; kraken reward improved; final resource requirement increased; overall difficulty reduced.\n• Minor reordering of islands.\n• An officer will now be prioritised for the captain role if the captain disconnects.
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
@ -50,6 +50,7 @@ location_displayname_standard_1=Isle of Buried Treasure
location_displayname_standard_variant_1=Secluded Dells
location_displayname_swamp_1=Poisonous Fen
location_displayname_walkways_1=Frozen Pools
location_displayname_cave_1=Mysterious Caves
location_displayname_sea_1=
location_displayname_dock_1=Dock
location_displayname_lobby_1=Starting Dock
@ -70,6 +71,7 @@ parrot_kraken_warning=400 leagues coming up? What are those pink things I spy...
parrot_radioactive_tip_1=We'll need uranium-235 to push away from this island...
parrot_radioactive_tip_2=The biters don't care if we pollute here, but they evolve fast.
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!
@ -103,6 +105,8 @@ victory_continue_reminder=If you wish to continue the game, click up top.
crew_disband_tick_message=The crew will disband in 20 seconds.
private_run_lock_expired=Private lock of __1__ run has expired. Anyone can join this crew now.
plank=__1__ planked __2__!
plank_error_invalid_player=Command error: Player is not a crewmember.
plank_error_self=Command error: Can't plank yourself.
@ -129,7 +133,7 @@ death_pushed_into_water_by_cannon=__1__ was pushed into water by a cannon.
granted_rocket_launch=Rocket launched.
granted_kraken_kill=Kraken killed.
granted_periodic_barrel=
granted_periodic_resource=Free resources granted for staying in this island.
granted_quest_complete=Quest completed.
granted_1=__1__ __2__.
@ -172,9 +176,10 @@ market_description_upgrade_power=Upgrade the ship's passive power generators.
market_description_upgrade_hold=Purchase an extra hold.
market_description_upgrade_merchants=Unlock merchant ships on future islands.
market_description_upgrade_rockets=Unlock the sale of rockets at island markets.
market_description_upgrade_turrets=Upgrade your ship's artilerry turrets max health and also fully heal them.
market_description_purchase_class=Purchase the class __1__.
market_description_extra_time_at_sea=Relax at sea: Increase the next destination's loading time by 60 seconds.
market_description_reroll_prices=Reroll prices.
market_event_sell=__1__ sold __2__ for __3__.
market_event_trade=__1__ traded away __2__ for __3__.
@ -197,6 +202,7 @@ upgrade_hold_crowsnest_form=Extra Hold
upgrade_power_crowsnest_form=Power
upgrade_merchants_crowsnest_form=Unlock Merchants
upgrade_rockets_crowsnest_form=Unlock Rockets
upgrade_cannons_crowsnest_form=Upgrade Cannons
@ -223,7 +229,7 @@ class_definition_for=Class definition for
class_deckhand=Deckhand
# class_deckhand_explanation=They move faster and generate ore for the cabin whilst onboard above deck.
class_deckhand_explanation_advanced=They move __1__% times faster and generate ore (with current crew size +__2__ every __3__ seconds) for the cabin whilst onboard above deck.
class_deckhand_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst onboard above deck.
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).
@ -238,10 +244,10 @@ class_merchant=Merchant
class_merchant_explanation_advanced=They generate 50 doubloons per league.
class_shoresman=Shoresman
# class_shoresman_explanation=They move slightly faster and generate ore for the cabin whilst offboard.
class_shoresman_explanation_advanced=They move __1__% times faster and generate ore (with current crew size +__2__ every __3__ seconds) for the cabin whilst offboard.
class_shoresman_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst offboard.
class_boatswain=Boatswain
# class_boatswain_explanation=They move faster and generate ore for the cabin whilst below deck.
class_boatswain_explanation_advanced=They move __1__% times faster and generate ore (with current crew size +__2__ every __3__ seconds) for the cabin whilst below deck.
class_boatswain_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst below deck.
class_prospector=Prospector
# class_prospector_explanation=They find more resources when handmining.
class_prospector_explanation_advanced=They find more resources when handmining.
@ -352,6 +358,7 @@ crew_leave=__1__ left the crew.
crew_launch=[__1__] Launched.
crew_disband=[__1__] Disbanded after __2__.
proposal_propose=__1__ proposed the run __2__ [Capacity __3__].
proposal_propose_private=__1__ proposed the private run __2__ [Capacity __3__].
proposal_retracted=Proposal __1__ retracted.
proposal_abandoned=Proposal __1__ abandoned.
@ -367,8 +374,8 @@ loss_cannon_destroyed=Game over — cannon destroyed.
loss_out_of_fuel=Game over — out of fuel.
loss_silo_destroyed=Game over — silo destroyed.
loss_silo_destroyed_before_necessary_launch=Game over — silo destroyed before a necessary launch.
loss_rest_of_message_long=Playtime: __1__ since 1st island. Crewmembers: __2__
loss_rest_of_message_short=Playtime: __1__ since 1st island.
loss_rest_of_message_long=Playtime: __1__ since 1st island. Leagues travelled: __2__. Crewmembers: __3__.
loss_rest_of_message_short=Playtime: __1__ since 1st island. Leagues travelled: __2__.
@ -508,6 +515,17 @@ gui_runs_proposal_maker_capacity=Capacity
gui_runs_proposal_maker_capacity_disabled=This capacity setting isn't available at the moment.
gui_runs_proposal_maker_propose=Propose
gui_runs_proposal_maker_no_limit=No limit
gui_runs_proposal_maker_private=Private
gui_runs_proposal_maker_private_tooltip=Sets your run to private, which protects the run by password.\nOnce the run has launched, only people who know password will be able to join the crew.\nPrivate run becomes public if the crew is empty or inactive for __1__ hours.
gui_runs_proposal_maker_password=Password
gui_runs_proposal_maker_confirm_password=Confirm Password
gui_runs_proposal_maker_error_private_run_limit=All private run slots are occupied. Wait until private run slots free up to create your own.
gui_runs_proposal_maker_error_private_run_password_no_match=Passwords do not match.
gui_runs_proposal_maker_error_private_run_password_empty=Passwords can't be empty.
gui_join_private_run_info=This run is private and protected.\nPlease enter a password to join the crew.\nThis run will become public in __1__:__2__:__3__
gui_join_private_run_error_wrong_password=The password you've entered is incorrect.
gui_runs_launch=Launch run
gui_runs_launch_error_1=Gather endorsements from more pirates.
@ -552,6 +570,8 @@ gui_questframe_find=Island Quest: Ghosts\n\nFind the ghosts for a bonus.
gui_questframe_resourceflow=Island Quest: Resource Flow\n\nAchieve a production rate of a particular item for a bonus.
gui_questframe_resourcecount=Island Quest: Item Production\n\nSimply complete production of these items for a bonus, anywhere on the map.
gui_questframe_nodamage=Island Quest: No Damage\n\nLaunch a rocket without the silo taking damage.
gui_questframe_fish=Island Quest: Fishing season\n\nCatch enough fish for a bonus.
gui_questframe_compilatron=Island Quest: To the rescue\n\nFind and rescue compilatrons from underneath the rocks for a bouns.
gui_crew_tooltip_1=Your Crew\n\nPerform crew actions. Captains can manage crew and its members here.
gui_crew_tooltip_2=Your Crew\n\nYou're a free agent, so there's nothing to do here.

View File

@ -13,8 +13,8 @@ local _inspect = require 'utils.inspect'.inspect
-- local Structures = require 'maps.pirates.structures.structures'
local Boats = require 'maps.pirates.structures.boats.boats'
local Surfaces = require 'maps.pirates.surfaces.surfaces'
local Islands = require 'maps.pirates.surfaces.islands.islands'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
-- local Islands = require 'maps.pirates.surfaces.islands.islands'
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'
@ -61,7 +61,7 @@ function Public.Tick_actions(tickinterval)
end
-- if destination.subtype and destination.subtype == Islands.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 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.
local minute_cycle = {-- warning: use even seconds only
@ -114,7 +114,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 == Islands.enum.RADIOACTIVE) then
if not (Common.current_destination().subtype and Common.current_destination().subtype == IslandEnum.enum.RADIOACTIVE) then
pollution_available = pollution_available + pollution_to_eat
end
end
@ -411,7 +411,7 @@ function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spaw
if initial_spawner_count > 0 then
local spawnerscount = Common.spawner_count(surface)
if spawnerscount > 0 then
-- if Common.current_destination().subtype and Common.current_destination().subtype == Islands.enum.RADIOACTIVE then
-- if Common.current_destination().subtype and Common.current_destination().subtype == IslandEnum.enum.RADIOACTIVE then
-- -- destroying spawners doesn't do quite as much here:
-- base_pollution_cost_multiplier = (initial_spawner_count/spawnerscount)^(1/3)
-- else
@ -439,11 +439,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 == IslandsCommon.enum.SWAMP then
if destination.subtype and 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 == IslandsCommon.enum.MAZE then
-- if destination.subtype and destination.subtype == IslandEnum.enum.MAZE then
-- base_pollution_cost_multiplier = base_pollution_cost_multiplier * 1.2 --biters 20% less aggressive
-- end

View File

@ -14,7 +14,7 @@ local Ai = require 'maps.pirates.ai'
local Boats = require 'maps.pirates.structures.boats.boats'
local Surfaces = require 'maps.pirates.surfaces.surfaces'
-- local Progression = require 'maps.pirates.progression'
local Islands = require 'maps.pirates.surfaces.islands.islands'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Roles = require 'maps.pirates.roles.roles'
local Gui = require 'maps.pirates.gui.gui'
-- local Sea = require 'maps.pirates.surfaces.sea.sea'
@ -34,6 +34,7 @@ local Loot = require 'maps.pirates.loot'
local Task = require 'utils.task'
local Token = require 'utils.token'
local Classes = require 'maps.pirates.roles.classes'
local Ores = require 'maps.pirates.ores'
local Server = require 'utils.server'
-- local Modifers = require 'player_modifiers'
@ -108,7 +109,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 == Islands.enum.MAZE then
if destination and destination.type and destination.subtype 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
@ -498,7 +499,7 @@ local function damage_dealt_by_players_changes(event)
for _, p2 in pairs(nearby_players) do
if p2.player and p2.player.valid then
local p2_index = p2.player.index
if event.entity.valid and player_index ~= p2_index and memory.classes_table[p2_index] and memory.classes_table[p2_index] == Classes.enum.QUARTERMASTER then
if event.entity.valid and player_index ~= p2_index and Classes.get_class(p2_index) == Classes.enum.QUARTERMASTER then
event.entity.damage((Balance.quartermaster_bonus_physical_damage - 1) * event.final_damage_amount, character.force, 'impact', character) --triggers this function again, but not physical this time
end
end
@ -527,7 +528,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 == Islands.enum.SWAMP) then return end
if not (destination and destination.subtype and destination.subtype == IslandEnum.enum.SWAMP) then return end
if not (destination.surface_name == entity.surface.name) then return end
@ -545,7 +546,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 == Islands.enum.MAZE) then return end
if not (destination and destination.subtype and destination.subtype == IslandEnum.enum.MAZE) then return end
if not (destination.surface_name == entity.surface.name) then return end
@ -690,15 +691,9 @@ end
function Public.load_some_map_chunks_random_order(destination_index, fraction) -- The reason we might want to do this is because of algorithms like the labyrinth code, which make directionally biased patterns if you don't generate chunks in a random order
local memory = Memory.get_crew_memory()
local destination_data = memory.destinations[destination_index]
if not destination_data then return end
local surface_name = destination_data.surface_name
if not surface_name then return end
local surface = game.surfaces[surface_name]
function Public.load_some_map_chunks_random_order(surface, destination_data, fraction) -- The reason we might want to do this is because of algorithms like the labyrinth code, which make directionally biased patterns if you don't generate chunks in a random order
if not surface then return end
if not destination_data then return end
local shuffled_chunks
if not destination_data.dynamic_data then destination_data.dynamic_data = {} end
@ -754,21 +749,25 @@ end
local function event_on_player_mined_entity(event)
if not event.player_index then return end
local player = game.players[event.player_index]
if not player.valid then return end
local entity = event.entity
if not entity.valid then return end
local crew_id = Common.get_id_from_force_name(player.force.name)
Memory.set_working_id(crew_id)
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
local entity = event.entity
if not entity.valid then return end
if player.surface.name == 'gulag' then
event.buffer.clear()
return
end
local class = Classes.get_class(event.player_index)
if entity.type == 'tree' then
if not event.buffer then return end
local available = destination.dynamic_data.wood_remaining
@ -776,29 +775,16 @@ local function event_on_player_mined_entity(event)
if available and destination.type == Surfaces.enum.ISLAND then
if destination and destination.subtype and destination.subtype == Islands.enum.MAZE then
if destination.subtype == IslandEnum.enum.MAZE then
if Math.random(1, 38) == 1 then
tick_tack_trap(memory.enemy_force_name, entity.surface, entity.position)
return
end
local give = {}
if memory.classes_table and memory.classes_table[event.player_index] then
if memory.classes_table[event.player_index] == Classes.enum.LUMBERJACK then
give[#give + 1] = {name = 'wood', count = 1}
Classes.lumberjack_bonus_items(give)
-- wood lord is disabled
-- elseif memory.classes_table[event.player_index] == Classes.enum.WOOD_LORD then
-- give[#give + 1] = {name = 'wood', count = 1}
-- give[#give + 1] = {name = 'iron-ore', count = 1}
-- give[#give + 1] = {name = 'copper-ore', count = 1}
-- give[#give + 1] = {name = 'coal', count = 1}
-- if Math.random(every_nth_tree_gives_coins) == 1 then
-- local a = 12
-- give[#give + 1] = {name = 'coin', count = a}
-- memory.playtesting_stats.coins_gained_by_trees_and_rocks = memory.playtesting_stats.coins_gained_by_trees_and_rocks + a
-- end
end
if class == Classes.enum.LUMBERJACK then
give[#give + 1] = {name = 'wood', count = 1}
Classes.lumberjack_bonus_items(give)
end
if #give > 0 then
@ -813,19 +799,9 @@ local function event_on_player_mined_entity(event)
destination.dynamic_data.wood_remaining = destination.dynamic_data.wood_remaining - amount
if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.LUMBERJACK then
if class == Classes.enum.LUMBERJACK then
give[#give + 1] = {name = 'wood', count = amount}
Classes.lumberjack_bonus_items(give)
-- elseif memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.WOOD_LORD then
-- give[#give + 1] = {name = 'wood', count = amount + 3}
-- give[#give + 1] = {name = 'iron-ore', count = 1}
-- give[#give + 1] = {name = 'copper-ore', count = 1}
-- give[#give + 1] = {name = 'coal', count = 1}
-- if Math.random(every_nth_tree_gives_coins) == 1 then
-- local a = 12
-- give[#give + 1] = {name = 'coin', count = a}
-- memory.playtesting_stats.coins_gained_by_trees_and_rocks = memory.playtesting_stats.coins_gained_by_trees_and_rocks + a
-- end
else
give[#give + 1] = {name = 'wood', count = amount}
if Math.random(Balance.every_nth_tree_gives_coins) == 1 then --tuned
@ -843,15 +819,31 @@ local function event_on_player_mined_entity(event)
elseif entity.type == 'fish' then
if not event.buffer then return end
local fish_amount
local to_give = {}
if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.MASTER_ANGLER then
Common.give(player, {{name = 'raw-fish', count = Balance.base_caught_fish_amount + Balance.master_angler_fish_bonus}, {name = 'coin', count = Balance.master_angler_coin_bonus}}, entity.position)
elseif memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.DREDGER then
local to_give = {{name = 'raw-fish', count = Balance.base_caught_fish_amount + Balance.dredger_fish_bonus}}
if class == Classes.enum.MASTER_ANGLER then
fish_amount = Balance.base_caught_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 = Balance.base_caught_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]
Common.give(player, to_give, entity.position)
else
Common.give(player, {{name = 'raw-fish', count = Balance.base_caught_fish_amount}}, entity.position)
fish_amount = Balance.base_caught_fish_amount
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
event.buffer.clear()
@ -903,12 +895,35 @@ local function event_on_player_mined_entity(event)
-- local starting = destination.static_params.starting_rock_material
if available and destination.type == Surfaces.enum.ISLAND then
if destination and destination.subtype and destination.subtype == Islands.enum.MAZE then
if destination.subtype == IslandEnum.enum.MAZE then
if Math.random(1, 35) == 1 then
tick_tack_trap(memory.enemy_force_name, entity.surface, entity.position)
return
end
elseif destination.subtype == IslandEnum.enum.CAVE then
Ores.try_give_ore(player, entity.position, entity.name)
if Math.random(1, 35) == 1 then
tick_tack_trap(memory.enemy_force_name, entity.surface, entity.position)
elseif Math.random(1, 20) == 1 then
entity.surface.create_entity({name = 'compilatron', position = entity.position, force = memory.force})
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.COMPILATRON then
destination.dynamic_data.quest_progress = destination.dynamic_data.quest_progress + 1
Quest.try_resolve_quest()
end
end
elseif Math.random(1, 10) == 1 then
if Math.random(1, 4) == 1 then
entity.surface.create_entity{name = Common.get_random_worm_type(memory.evolution_factor), position = entity.position, force = memory.enemy_force_name}
else
entity.surface.create_entity{name = Common.get_random_unit_type(memory.evolution_factor), position = entity.position, force = memory.enemy_force_name}
end
end
else
local c = event.buffer.get_contents()
table.sort(c, function(a,b) return a.name < b.name end)
@ -986,22 +1001,19 @@ local function base_kill_rewards(event)
end
end
local class
local class_is_chef = false
if revenge_target and
revenge_target.valid and
revenge_target.player and
revenge_target.player.index and
memory.classes_table and
memory.classes_table[revenge_target.player.index]
revenge_target.player.index
then
class = memory.classes_table[revenge_target.player.index]
class_is_chef = Classes.get_class(revenge_target.player.index) == Classes.enum.CHEF
end
local class_is_chef = (class and class == Classes.enum.CHEF) and true or false
-- no worm loot in the maze except for chefs:
local maze = (destination.subtype and destination.subtype == Islands.enum.MAZE)
local maze = destination.subtype == IslandEnum.enum.MAZE
if maze and not (entity_name == 'biter-spawner' or entity_name == 'spitter-spawner') and not (class_is_chef) then return end
local iron_amount
@ -1088,7 +1100,8 @@ local function base_kill_rewards(event)
local short_form = (not iron_amount) and true or false
if revenge_target then
-- revenge_target.player can be nil if player kills itself
if revenge_target and revenge_target.player then
Common.give(revenge_target.player, stack, revenge_target.player.position, short_form, entity.surface, entity.position)
else
if event.cause and event.cause.valid and event.cause.position then
@ -1287,26 +1300,7 @@ local function event_on_research_finished(event)
end
end
-- even after research, force disable these:
-- p_force.recipes['underground-belt'].enabled = false
-- p_force.recipes['fast-underground-belt'].enabled = false
-- p_force.recipes['express-underground-belt'].enabled = false
p_force.recipes['pistol'].enabled = false
p_force.recipes['centrifuge'].enabled = false
-- p_force.recipes['flamethrower-turret'].enabled = false
p_force.recipes['locomotive'].enabled = false
p_force.recipes['car'].enabled = false
p_force.recipes['cargo-wagon'].enabled = false
p_force.recipes['slowdown-capsule'].enabled = false
p_force.recipes['nuclear-fuel'].enabled = false
-- p_force.recipes['rail'].enabled = false
p_force.recipes['speed-module'].enabled = false
p_force.recipes['tank'].enabled = false
p_force.recipes['cannon-shell'].enabled = false
p_force.recipes['explosive-cannon-shell'].enabled = false
-- and since we can't build tanks anyway, let's disable this for later:
p_force.recipes['uranium-cannon-shell'].enabled = false
p_force.recipes['explosive-uranium-cannon-shell'].enabled = false
Crew.disable_recipes(p_force)
end
local function event_on_player_joined_game(event)
@ -1322,6 +1316,7 @@ local function event_on_player_joined_game(event)
if _DEBUG then
game.print('Debug mode on. Use /go to get started, /1 /4 /32 etc to change game speed.')
game.print('Current version: ' .. CoreData.version_string)
end
local crew_to_put_back_in = nil
@ -1366,7 +1361,7 @@ local function event_on_player_joined_game(event)
local ages = {}
for _, memory in pairs(global_memory.crew_memories) do
if Common.is_id_valid(memory.id)
and memory.crewstatus
and (not memory.run_is_private)
and memory.crewstatus == Crew.enum.ADVENTURING
and memory.capacity
and memory.crewplayerindices
@ -1553,7 +1548,7 @@ function Public.player_entered_vehicle(player, vehicle)
local surfacedata = Surfaces.SurfacesCommon.decode_surface_name(player.surface.name)
if vehicle.name == 'car' then
-- a way to make simple cars work
-- A way to make player driven vehicles work
if vehicle.minable then
return
end
@ -1574,6 +1569,8 @@ function Public.player_entered_vehicle(player, vehicle)
end
vehicle.color = {148, 106, 52}
player.driving = false
elseif vehicle.name == 'locomotive' then
if surfacedata.type ~= Surfaces.enum.HOLD and surfacedata.type ~= Surfaces.enum.LOBBY and Math.abs(player_boat_relative_pos.y) < 8 then --<8 in order not to enter holds of boats you haven't bought yet
@ -1588,9 +1585,9 @@ function Public.player_entered_vehicle(player, vehicle)
end
player.play_sound{path = "utility/picked_up_item"}
end
end
player.driving = false
player.driving = false
end
end
local function event_on_player_driving_changed_state(event)
@ -1632,7 +1629,7 @@ function Public.event_on_chunk_generated(event)
local memory = Memory.get_crew_memory()
if type == Surfaces.enum.ISLAND and memory.destinations and memory.destinations[chunk_destination_index] then
local destination = memory.destinations[chunk_destination_index]
scope = Surfaces.get_scope(destination)
scope = Surfaces.get_scope(surface_name_decoded)
static_params = destination.static_params
other_map_generation_data = destination.dynamic_data.other_map_generation_data or {}
terraingen_coordinates_offset = static_params.terraingen_coordinates_offset
@ -1698,17 +1695,19 @@ function Public.event_on_chunk_generated(event)
end
end
chunk_structures_fn{
true_left_top = chunk_left_top,
left_top = Utils.psum{chunk_left_top, {1, terraingen_coordinates_offset}},
noise_generator = noise_generator,
static_params = static_params,
specials = specials,
entities = entities,
seed = seed,
other_map_generation_data = other_map_generation_data,
biter_base_density_scale = Balance.biter_base_density_scale()
}
if chunk_structures_fn then
chunk_structures_fn{
true_left_top = chunk_left_top,
left_top = Utils.psum{chunk_left_top, {1, terraingen_coordinates_offset}},
noise_generator = noise_generator,
static_params = static_params,
specials = specials,
entities = entities,
seed = seed,
other_map_generation_data = other_map_generation_data,
biter_base_density_scale = Balance.biter_base_density_scale()
}
end
local tiles_corrected = {}
for i = 1, #tiles do
@ -1738,11 +1737,11 @@ function Public.event_on_chunk_generated(event)
-- recoordinatize:
special.position = Utils.psum{special.position, {-1, terraingen_coordinates_offset}}
if special.name and special.name == 'buried-treasure' then
if special.name == 'buried-treasure' then
if destination.dynamic_data.buried_treasure and crewid ~= 0 then
destination.dynamic_data.buried_treasure[#destination.dynamic_data.buried_treasure + 1] = {treasure = Loot.buried_treasure_loot(), position = special.position}
end
elseif special.name and special.name == 'chest' then
elseif special.name == 'chest' then
local e = surface.create_entity{name = 'wooden-chest', position = special.position, force = memory.ancient_friendly_force_name}
if e and e.valid then
e.minable = false
@ -1759,6 +1758,38 @@ function Public.event_on_chunk_generated(event)
local inv = e.get_inventory(defines.inventory.chest)
local loot = Loot.wooden_chest_loot()
for i = 1, #loot do
local l = loot[i]
inv.insert(l)
end
end
elseif special.name == 'market' then
local e = surface.create_entity{name = 'market', position = special.position, force = memory.ancient_friendly_force_name}
if e and e.valid then
e.minable = false
e.rotatable = false
e.destructible = false
for _, o in pairs(special.offers) do
e.add_market_item(o)
end
end
elseif special.name == 'big-ship-wreck-2' or special.name == 'big-ship-wreck-1' then
local e = surface.create_entity{name = special.name, position = special.position, force = memory.ancient_friendly_force_name}
if e and e.valid then
e.minable = false
e.rotatable = false
e.destructible = false
local inv = e.get_inventory(defines.inventory.chest)
local loot
if Math.random(3) == 1 then
loot = Loot.iron_chest_loot()
else
loot = Loot.wooden_chest_loot()
end
for i = 1, #loot do
local l = loot[i]
inv.insert(l)

View File

@ -9,7 +9,7 @@ local Ai = require 'maps.pirates.ai'
local Structures = require 'maps.pirates.structures.structures'
local Boats = require 'maps.pirates.structures.boats.boats'
local Islands = require 'maps.pirates.surfaces.islands.islands'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Surfaces = require 'maps.pirates.surfaces.surfaces'
local PiratesApiEvents = require 'maps.pirates.api_events'
local Roles = require 'maps.pirates.roles.roles'
@ -85,21 +85,39 @@ function Public.prevent_disembark(tickinterval)
local destination = Common.current_destination()
local boat = memory.boat
if boat and boat.state and (boat.state == Boats.enum_state.RETREATING or (boat.state == Boats.enum_state.LEAVING_DOCK and (not (memory.crewstatus and memory.crewstatus == Crew.enum.LEAVING_INITIAL_DOCK)))) then
if boat and (boat.state == Boats.enum_state.RETREATING or (boat.state == Boats.enum_state.LEAVING_DOCK and memory.crewstatus ~= Crew.enum.LEAVING_INITIAL_DOCK)) then
if not destination.dynamic_data.cant_disembark_players then destination.dynamic_data.cant_disembark_players = {} end
local ps = destination.dynamic_data.cant_disembark_players
for _, player in pairs(game.connected_players) do
if player.surface and player.surface.valid and boat.surface_name and player.surface.name == boat.surface_name and Boats.on_boat(boat, player.position) then
if player.surface and player.surface.valid and player.surface.name == boat.surface_name and Boats.on_boat(boat, player.position) then
ps[player.index] = true
end
end
for _, player in pairs(game.connected_players) do
if player.surface and player.surface.valid and boat.surface_name and player.surface.name == boat.surface_name and ps[player.index] and (not Boats.on_boat(boat, player.position)) and (not (player.controller_type == defines.controllers.spectator)) then
if player.surface and player.surface.valid and player.surface.name == boat.surface_name and ps[player.index] and (not Boats.on_boat(boat, player.position)) and player.controller_type ~= defines.controllers.spectator then
Common.notify_player_error(player, {'pirates.error_disembark'})
-- player.teleport(memory.spawnpoint)
if player.driving then
local vehicle = player.vehicle
if vehicle then
local passenger = vehicle.get_passenger()
if passenger then
vehicle.set_passenger(nil)
local p = passenger.surface.find_non_colliding_position('character', memory.spawnpoint, 5, 0.1)
if p then
passenger.teleport(p)
else
passenger.teleport(memory.spawnpoint)
end
end
vehicle.set_driver(nil)
end
end
local p = player.surface.find_non_colliding_position('character', memory.spawnpoint, 5, 0.1)
if p then
player.teleport(p)
@ -116,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 == Islands.enum.RED_DESERT)) then
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 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
@ -288,16 +306,16 @@ function Public.periodic_free_resources(tickinterval)
if memory.game_lost then return end
local destination = Common.current_destination()
local boat = memory.boat
if not (destination and destination.type and destination.type == Surfaces.enum.ISLAND and boat and boat.surface_name and boat.surface_name == destination.surface_name) then return end
if not (destination and destination.type == Surfaces.enum.ISLAND and boat and boat.surface_name == destination.surface_name) then return end
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 == Islands.enum.RADIOACTIVE) then -- every 150 seconds
if game.tick % (300*30) == 0 and (destination and destination.subtype 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
if not (force and force.valid) then return end
local message = {'pirates.granted_1', {'pirates.granted_periodic_barrel'}, count .. ' [item=sulfuric-acid-barrel]'}
local message = {'pirates.granted_1', {'pirates.granted_periodic_resource'}, count .. ' [item=sulfuric-acid-barrel]'}
Common.notify_force_light(force, message)
end
end
@ -571,7 +589,7 @@ function Public.place_cached_structures(tickinterval)
surface.create_entity{
name = 'crude-oil',
position = p,
amount = Balance.pick_special_pumpjack_oil_amount()
amount = Balance.pick_default_oil_amount()
}
end
local e2 = surface.create_entity{name = c.name, position = p, direction = e.direction, force = force_name, amount = c.amount}
@ -583,6 +601,10 @@ function Public.place_cached_structures(tickinterval)
elseif c.type == 'vehicles' then
local c2 = {type = c.type, force_name = force_name, built_entities = {}}
if memory.overworldx >= 1000 then
c.name = 'tank'
end
for _, e in pairs(c.instances) do
local p = Utils.psum{position, e.position, c.offset}
local e2 = surface.create_entity{name = c.name, position = p, direction = e.direction}
@ -818,7 +840,7 @@ function Public.boat_movement_tick(tickinterval)
Structures.Boats.currentdestination_move_boat_natural()
end
elseif boat.speedticker2 >= Common.boat_steps_at_a_time then
if surface_type and surface_type == Surfaces.enum.ISLAND and boat and boat.state and boat.state == Boats.enum_state.APPROACHING then
if surface_type == Surfaces.enum.ISLAND and boat and boat.state == Boats.enum_state.APPROACHING then
Structures.Boats.currentdestination_try_move_boat_steered()
end
boat.speedticker2 = 0
@ -1011,7 +1033,7 @@ function Public.loading_update(tickinterval)
local total = Common.map_loading_ticks_atsea
if currentdestination.type == Surfaces.enum.DOCK then
total = Common.map_loading_ticks_atsea_dock
elseif currentdestination.type == Surfaces.enum.ISLAND and currentdestination.subtype == Surfaces.Island.enum.MAZE then
elseif currentdestination.type == Surfaces.enum.ISLAND and currentdestination.subtype == IslandEnum.enum.MAZE then
total = Common.map_loading_ticks_atsea_maze
end
@ -1030,7 +1052,10 @@ function Public.loading_update(tickinterval)
Progression.progress_to_destination(destination_index)
memory.loadingticks = 0
else
PiratesApiEvents.load_some_map_chunks_random_order(destination_index, fraction) --random order is good for maze world
PiratesApiEvents.load_some_map_chunks_random_order(surface, currentdestination, fraction) --random order is good for maze world
if currentdestination.subtype == IslandEnum.enum.CAVE then
PiratesApiEvents.load_some_map_chunks_random_order(currentdestination.dynamic_data.cave_miner.cave_surface, currentdestination, fraction)
end
end
end
@ -1167,7 +1192,7 @@ function Public.slower_boat_tick(tickinterval)
end
local p = memory.boat.position
if p and (not (destination.subtype and destination.subtype == IslandsCommon.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 (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
local pollution = Balance.boat_passive_pollution_per_minute(destination.dynamic_data.timer) / 3600 * tickinterval
game.surfaces[destination.surface_name].pollute(p, pollution)
@ -1215,7 +1240,7 @@ function Public.minimap_jam(tickinterval)
if memory.overworldx == Common.maze_minimap_jam_league and memory.boat and memory.boat.state == Boats.enum_state.LANDED then
local destination = Common.current_destination()
if destination.type == Surfaces.enum.ISLAND and destination.subtype == Surfaces.Island.enum.MAZE then
if destination.type == Surfaces.enum.ISLAND and destination.subtype == IslandEnum.enum.MAZE then
if not destination.surface_name then return end
local surface = game.surfaces[destination.surface_name]
local force = memory.force
@ -1491,36 +1516,77 @@ function Public.update_alert_sound_frequency_tracker()
end
end
-- Check for cliff explosives in chest.
function Public.check_for_cliff_explosives_in_hold_wooden_chests()
local memory = Memory.get_crew_memory()
local input_chests = memory.hold_surface_destroyable_wooden_chests
local queued_chests_timers = memory.hold_surface_timers_of_wooden_chests_queued_for_destruction
local tick_tack_timer = 5 -- how long it takes before chests detonate
if not input_chests then return end
for i, chest in ipairs(input_chests) do
-- check which chests have cliff explosives in them
for i, chest in pairs(input_chests) do
-- @TODO: decide what to do when chest is invalid (perhaps it was destroyed by some future feature)
if chest and chest.valid then
local item_count = chest.get_item_count('cliff-explosives')
if item_count and item_count > 0 then
local surface = chest.surface
local explosion = {
name = 'wooden-chest-explosion',
position = chest.position
}
local remnants = {
name = 'wooden-chest-remnants',
position = chest.position
}
chest.destroy()
surface.create_entity(explosion)
surface.create_entity(remnants)
table.fast_remove(memory.hold_surface_destroyable_wooden_chests, i)
if not queued_chests_timers[i] then
queued_chests_timers[i] = tick_tack_timer
end
end
end
end
-- update chest timers and when timer reaches 0 explode them
for i, _ in pairs(queued_chests_timers) do
local chest = input_chests[i]
if chest and chest.valid then
local surface = chest.surface
queued_chests_timers[i] = queued_chests_timers[i] - 1
local timer = queued_chests_timers[i]
if timer <= 0 then
-- check if sneaky players didn't decide to remove the explosives just before the explosion
local item_count = chest.get_item_count('cliff-explosives')
if item_count and item_count > 0 then
local explosion = {
name = 'wooden-chest-explosion',
position = chest.position
}
local remnants = {
name = 'wooden-chest-remnants',
position = chest.position
}
chest.destroy()
surface.create_entity(explosion)
surface.create_entity(remnants)
input_chests[i] = nil
end
queued_chests_timers[i] = nil
else
local tick_tacks = {'*tick*', '*tick*', '*tack*', '*tak*', '*tik*', '*tok*'}
surface.create_entity(
{
name = 'flying-text',
position = chest.position,
text = tick_tacks[Math.random(#tick_tacks)],
color = {r = 0.75, g = 0.75, b = 0.75}
}
)
end
else
-- we probably don't want to have it in the queue anymore if it's invalid now, do we?
queued_chests_timers[i] = nil
end
end
end
-- Code taken from Mountain fortress
local function equalise_fluid_storage_pair(storage1, storage2)
if not storage1.valid then
@ -1598,4 +1664,22 @@ function Public.revealed_buried_treasure_distance_check()
end
end
function Public.update_private_run_lock_timer(tickinterval)
local memory = Memory.get_crew_memory()
if memory.run_is_private then
if Common.activecrewcount() <= 0 then
if memory.private_run_lock_timer > 0 then
memory.private_run_lock_timer = memory.private_run_lock_timer - tickinterval
if memory.private_run_lock_timer <= 0 then
Common.notify_game({'pirates.private_run_lock_expired', memory.name})
memory.run_is_private = false
end
end
else
memory.private_run_lock_timer = 60 * 60 * 60 * CoreData.private_run_lock_amount_hr
end
end
end
return Public

View File

@ -45,14 +45,14 @@ Public.hatamoto_damage_dealt_with_melee = 45
Public.iron_leg_damage_taken_multiplier = 0.18
Public.iron_leg_iron_ore_required = 3000
Public.deckhand_extra_speed = 1.25
Public.deckhand_ore_grant_multiplier = 2
Public.deckhand_ore_scaling_enabled = true
Public.deckhand_ore_grant_multiplier = 5
Public.deckhand_ore_scaling_enabled = false
Public.boatswain_extra_speed = 1.25
Public.boatswain_ore_grant_multiplier = 4
Public.boatswain_ore_scaling_enabled = true
Public.boatswain_ore_grant_multiplier = 8
Public.boatswain_ore_scaling_enabled = false
Public.shoresman_extra_speed = 1.1
Public.shoresman_ore_grant_multiplier = 2
Public.shoresman_ore_scaling_enabled = true
Public.shoresman_ore_grant_multiplier = 5
Public.shoresman_ore_scaling_enabled = false
Public.quartermaster_range = 19
Public.quartermaster_bonus_physical_damage = 1.3
Public.quartermaster_ore_scaling_enabled = false
@ -61,6 +61,7 @@ Public.scout_damage_taken_multiplier = 1.25
Public.scout_damage_dealt_multiplier = 0.6
Public.fisherman_reach_bonus = 10
Public.lumberjack_coins_from_tree = 12
Public.lumberjack_ore_base_amount = 4
Public.master_angler_reach_bonus = 16
Public.master_angler_fish_bonus = 2
Public.master_angler_coin_bonus = 20
@ -145,7 +146,9 @@ end
function Public.game_slowness_scale()
-- return 1 / Public.crew_scale()^(55/100) / Math.sloped(Common.difficulty_scale(), 1/4) --changed crew_scale factor significantly to help smaller crews
return 1 / Public.crew_scale()^(50/100) / Math.sloped(Common.difficulty_scale(), 1/4) --changed crew_scale factor significantly to help smaller crews
-- return 1 / (Public.crew_scale()^(50/100) / Math.sloped(Common.difficulty_scale(), 1/4)) --changed crew_scale factor significantly to help smaller crews
return Math.sloped(Common.difficulty_scale(), 1/4) / Public.crew_scale()^(50/100)
end
@ -183,16 +186,20 @@ end
function Public.fuel_depletion_rate_static()
if (not Common.overworldx()) then return 0 end
local T = Public.expected_time_on_island()
local rate
if Common.overworldx() > 0 then
rate = 570 * (0 + (Common.overworldx()/40)^(9/10)) * Public.crew_scale()^(1/8) * Math.sloped(Common.difficulty_scale(), 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
-- With this formula coal consumption becomes 1x, 2x, 3x and 4x with 1, 3, 6, 9 crew members respectively
-- 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 = 570 * ((Common.overworldx()/40)^(9/10)) * Public.crew_scale()^(1/8) * Math.sloped(Common.difficulty_scale(), 65/100) / T
return -rate
-- With this formula coal consumption becomes 1x, 1.24x, 1.44x and 1.57x with 1, 3, 6, 9 crew members respectively.
-- Coal consumption should scale slowly because:
-- - More people doesn't necessarily mean faster progression: people just focus on other things (and on some islands it's hard to "employ" every crew member to be productive, due to lack of activities).
-- - Although more players can setup miners faster, miners don't dig ore faster.
-- - It's not fun being punished when noobs(or just your casual friends) join game and don't contribute "enough" to make up for increased coal consumption (among other things).
return -0.2 * ((Common.overworldx()/40)^(9/10)) * Public.crew_scale()^(1/5) * Math.sloped(Common.difficulty_scale(), 40/100)
else
return 0
end
end
function Public.fuel_depletion_rate_sailing()
@ -390,15 +397,39 @@ function Public.island_richness_avg_multiplier()
end
function Public.resource_quest_multiplier()
return (1.0 + 0.075 * (Common.overworldx()/40)^(8/10)) * Math.sloped(Common.difficulty_scale(), 1/5) * (Public.crew_scale())^(1/10)
return (0.9 + 0.075 * (Common.overworldx()/40)^(8/10)) * Math.sloped(Common.difficulty_scale(), 1/5) * (Public.crew_scale())^(1/10)
end
function Public.quest_market_entry_price_scale()
return 0.85 * (1 + 0.030 * (Common.overworldx()/40 - 1)) * ((1 + Public.crew_scale())^(1/3)) * Math.sloped(Common.difficulty_scale(), 1/2) --whilst the scenario philosophy says that resource scales tend to be independent of crew size, we account slightly for the fact that more players tend to handcraft more
-- Whilst the scenario philosophy says that resource scales tend to be independent of crew size, we account slightly for the fact that more players tend to handcraft more
-- Idea behind formula: small scale for early islands, but scale linearly ~3-4 times every 25 islands (scaling and starting scale is more aggressive for higher difficulties)
-- Returned value examples
-- Assuming parameters:
-- crew_size = 3
-- difficulty = easy (0.5)
-- @NOTE: assuming starting island is 0th island
-- x = 40 (1st island): 0.419
-- x = 200 (5th island): 0.582
-- x = 600 (15th island): 0.992
-- x = 1000 (25th island): 1.401
return (1 + 0.05 * (Common.overworldx()/40 - 1)) * ((1 + Public.crew_scale())^(1/3)) * Math.sloped(Common.difficulty_scale(), 1/2) - 0.4
end
function Public.quest_furnace_entry_price_scale()
return 0.85 * (1 + 0.010 * (Common.overworldx()/40 - 1)) * ((1 + Public.crew_scale())^(1/3)) * Math.sloped(Common.difficulty_scale(), 1/2) --slower increase with time, because this is more time-constrained than resource-constrained
-- Slower increase with time, because this is more time-constrained than resource-constrained
-- Idea behind formula: small scale for early islands, but scale linearly ~2-3 times every 25 islands (scaling and starting scale is more aggressive for higher difficulties)
-- Returned value examples
-- Assuming parameters:
-- crew_size = 3
-- difficulty = easy (0.5)
-- @NOTE: assuming starting island is 0th island
-- x = 40 (1st island): 0.419
-- x = 200 (5th island): 0.517
-- x = 600 (15th island): 0.762
-- x = 1000 (25th island): 1.008
return (1 + 0.03 * (Common.overworldx()/40 - 1)) * ((1 + Public.crew_scale())^(1/3)) * Math.sloped(Common.difficulty_scale(), 1/2) - 0.4
end
function Public.apply_crew_buffs_per_league(force, leagues_travelled)
@ -434,14 +465,14 @@ function Public.kraken_evo_increase_per_shot()
end
function Public.kraken_evo_increase_per_second()
return 1/100 / 20
return (1/100) / 20
end
function Public.sandworm_evo_increase_per_spawn()
if _DEBUG then
return 1/100
else
return 1/100 * 1/7 * Math.sloped(Common.difficulty_scale(), 3/5)
return (1/100) * (1/7) * Math.sloped(Common.difficulty_scale(), 3/5)
end
end
@ -573,9 +604,31 @@ function Public.player_gun_speed_modifiers()
end
Public.starting_items_player = {['pistol'] = 1, ['firearm-magazine'] = 20, ['raw-fish'] = 4, ['medium-electric-pole'] = 20, ['iron-plate'] = 50, ['copper-plate'] = 20, ['iron-gear-wheel'] = 6, ['copper-cable'] = 20, ['burner-inserter'] = 2, ['gun-turret'] = 1}
Public.starting_items_player = {
['pistol'] = 1,
['firearm-magazine'] = 20,
['raw-fish'] = 4,
['medium-electric-pole'] = 20,
['iron-plate'] = 50,
['copper-plate'] = 20,
['iron-gear-wheel'] = 6,
['copper-cable'] = 20,
['burner-inserter'] = 2,
['gun-turret'] = 1
}
Public.starting_items_player_late = {['pistol'] = 1, ['firearm-magazine'] = 10, ['raw-fish'] = 4, ['small-electric-pole'] = 20, ['iron-plate'] = 50, ['copper-plate'] = 20, ['iron-gear-wheel'] = 6, ['copper-cable'] = 20, ['burner-inserter'] = 2, ['gun-turret'] = 1}
Public.starting_items_player_late = {
['pistol'] = 1,
['firearm-magazine'] = 10,
['raw-fish'] = 4,
['small-electric-pole'] = 20,
['iron-plate'] = 50,
['copper-plate'] = 20,
['iron-gear-wheel'] = 6,
['copper-cable'] = 20,
['burner-inserter'] = 2,
['gun-turret'] = 1
}
function Public.starting_items_crew_upstairs()
return {
@ -634,10 +687,10 @@ end
-- a: scaling
-- When the formula needs adjustments, I suggest changing scaling variable
-- Note: 3333 crude oil amount ~= 1% = 0.1/sec
function Public.pick_special_pumpjack_oil_amount()
function Public.pick_default_oil_amount()
local scaling = 50
local amount = scaling * Math.sqrt(1000000 * Common.game_completion_progress())
local extra_random_amount = Math.random(Math.ceil(0.2 * amount))
local extra_random_amount = Math.random(Math.max(1, Math.ceil(0.2 * amount)))
return amount + extra_random_amount
end

View File

@ -30,6 +30,7 @@ local enum = {
MORE_POWER = 'upgrade_power',
UNLOCK_MERCHANTS = 'unlock_merchants',
ROCKETS_FOR_SALE = 'rockets_for_sale',
UPGRADE_CANNONS = 'upgrade_cannons', -- heal and upgrade all ship's artilerry turrets max health
}
Public.enum = enum
Public.List = {
@ -37,6 +38,7 @@ Public.List = {
enum.MORE_POWER,
enum.UNLOCK_MERCHANTS,
enum.ROCKETS_FOR_SALE,
enum.UPGRADE_CANNONS,
}
Public.crowsnest_display_form = {
@ -44,6 +46,7 @@ Public.crowsnest_display_form = {
[enum.MORE_POWER] = {'pirates.upgrade_power_crowsnest_form'},
[enum.UNLOCK_MERCHANTS] = {'pirates.upgrade_merchants_crowsnest_form'},
[enum.ROCKETS_FOR_SALE] = {'pirates.upgrade_rockets_crowsnest_form'},
[enum.UPGRADE_CANNONS] = {'pirates.upgrade_cannons_crowsnest_form'},
}
-- WARNING: The dock market pulls from these values, but the Crowsnest caption pulls data from main_shop_data_1. So don't change one without the other
@ -52,6 +55,7 @@ Public.market_offer_form = {
[enum.EXTRA_HOLD] = {price = {{'coin', 7000}, {'coal', 500}}, offer = {type='nothing', effect_description={'pirates.market_description_upgrade_hold'}}},
[enum.UNLOCK_MERCHANTS] = {price = {{'coin', 14000}, {'coal', 1000}}, offer = {type='nothing', effect_description={'pirates.market_description_upgrade_merchants'}}},
[enum.ROCKETS_FOR_SALE] = {price = {{'coin', 21000}, {'coal', 1000}}, offer = {type='nothing', effect_description={'pirates.market_description_upgrade_rockets'}}},
[enum.UPGRADE_CANNONS] = {price = {{'repair-pack', 20}, {'coin', 5000}, {'coal', 800}}, offer = {type='nothing', effect_description={'pirates.market_description_upgrade_rockets'}}},
}
function Public.execute_upgade(upgrade_type, player)
@ -61,25 +65,34 @@ function Public.execute_upgade(upgrade_type, player)
if upgrade_type == enum.EXTRA_HOLD then
if player then
Common.notify_force(player.force,{'pirates.upgrade_hold',player.name})
Common.notify_force(player.force, {'pirates.upgrade_hold', player.name})
end
Hold.add_another_hold_surface()
elseif upgrade_type == enum.MORE_POWER then
if player then
Common.notify_force(player.force, {'pirates.upgrade_power',player.name})
Common.notify_force(player.force, {'pirates.upgrade_power', player.name})
end
boat.EEI_stage = boat.EEI_stage + 1
Boats.update_EEIs(boat)
elseif upgrade_type == enum.UNLOCK_MERCHANTS then
if player then
Common.notify_force(player.force,{'pirates.upgrade_merchants',player.name})
Common.notify_force(player.force, {'pirates.upgrade_merchants', player.name})
end
memory.merchant_ships_unlocked = true
elseif upgrade_type == enum.ROCKETS_FOR_SALE then
if player then
Common.notify_force(player.force,{'pirates.upgrade_rockets',player.name})
Common.notify_force(player.force, {'pirates.upgrade_rockets', player.name})
end
memory.rockets_for_sale = true
elseif upgrade_type == enum.UPGRADE_CANNONS then
if player then
Common.notify_force(player.force, {'pirates.upgraded_cannons', player.name})
end
Boats.upgrade_cannons()
end
end

View File

@ -9,23 +9,19 @@ local Server = require 'utils.server'
local Math = require 'maps.pirates.math'
local Ai = require 'maps.pirates.ai'
local Memory = require 'maps.pirates.memory'
local Gui = require 'maps.pirates.gui.gui'
local Common = require 'maps.pirates.common'
local CoreData = require 'maps.pirates.coredata'
local PlayerColors = require 'maps.pirates.player_colors'
local Utils = require 'maps.pirates.utils_local'
local Balance = require 'maps.pirates.balance'
local Crew = require 'maps.pirates.crew'
local Roles = require 'maps.pirates.roles.roles'
local Structures = require 'maps.pirates.structures.structures'
local Boats = require 'maps.pirates.structures.boats.boats'
local Surfaces = require 'maps.pirates.surfaces.surfaces'
local Overworld = require 'maps.pirates.overworld'
local Islands = require 'maps.pirates.surfaces.islands.islands'
local Progression = require 'maps.pirates.progression'
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
local Hold = require 'maps.pirates.surfaces.hold'
local PiratesApiEvents = require 'maps.pirates.api_events'
local Upgrades = require 'maps.pirates.boat_upgrades'
local Effects = require 'maps.pirates.effects'
@ -39,7 +35,6 @@ local CustomEvents = require 'maps.pirates.custom_events'
local Classes = require 'maps.pirates.roles.classes'
local Gui = require 'maps.pirates.gui.gui'
local GUIcolor = require 'maps.pirates.gui.color'
@ -232,27 +227,6 @@ end)
-- player.print('[color=gray]' .. Roles.get_classes_print_string() .. '[/color]')
-- end)
-- commands.add_command(
-- 'classinfo',
-- {'pirates.cmd_explain_classinfo'},
-- function(cmd)
-- local param = tostring(cmd.parameter)
-- local player = game.players[cmd.player_index]
-- if not Common.validate_player(player) then return end
-- if param and param ~= 'nil' then
-- local string = Roles.get_class_print_string(param, false)
-- if string then
-- Common.notify_player_expected(player, {'', {'pirates.class_definition_for'}, ' ', string})
-- else
-- Common.notify_player_error(player, {'pirates.cmd_error_invalid_class_name', param})
-- end
-- else
-- --Common.notify_player_expected(player, '/classinfo {classname} returns the definition of the named class.')
-- Common.notify_player_expected(player, {'', '/classinfo ', {'pirates.cmd_explain_classinfo'}})
-- end
-- end)
commands.add_command(
'classinfo',
{'pirates.cmd_explain_classinfo'},
@ -419,9 +393,8 @@ function(cmd)
local player = game.players[cmd.player_index]
local param = tostring(cmd.parameter)
if check_captain_or_admin(cmd) then
local memory = Memory.get_crew_memory()
if param and game.players[param] and game.players[param].index then
if memory.officers_table and memory.officers_table[game.players[param].index] then
if Common.is_officer(game.players[param].index) then
Roles.unmake_officer(player, game.players[param])
else
Roles.make_officer(player, game.players[param])
@ -484,24 +457,6 @@ function(cmd)
end
end)
-- Equip a class passed in parameter (although I think this command is redundant since there is /take command?)
commands.add_command(
'setclass',
{'pirates.cmd_explain_dev'},
function(cmd)
cmd_set_memory(cmd)
local param = tostring(cmd.parameter)
if check_admin(cmd) then
local player = game.players[cmd.player_index]
local memory = Memory.get_crew_memory()
if not Common.validate_player(player) then return end
if not memory.classes_table then memory.classes_table = {} end
memory.classes_table[player.index] = param
player.print('Set own class to ' .. param .. '.')
end
end)
commands.add_command(
'setevo',
{'pirates.cmd_explain_dev'},
@ -621,7 +576,9 @@ function(cmd)
local memory = Memory.get_crew_memory()
if not Common.is_id_valid(memory.id) then return end
local player = game.players[cmd.player_index]
Classes.try_unlock_class(param, player, true)
if not Classes.try_unlock_class(param, player, true) then
Common.notify_player_error(player, {'pirates.cmd_error_invalid_class_name', param})
end
end
end)
@ -1135,7 +1092,7 @@ if _DEBUG then
local param = tostring(cmd.parameter)
if check_admin(cmd) then
local player = game.players[cmd.player_index]
Server.to_discord_embed_raw(CoreData.comfy_emojis.monkas)
Server.to_discord_embed_raw(CoreData.comfy_emojis.despair)
end
end)
@ -1150,14 +1107,17 @@ if _DEBUG then
local player = game.players[cmd.player_index]
local memory = Memory.get_crew_memory()
if not Common.is_id_valid(memory.id) then return end
local boat = memory.boat
local scope = Boats.get_scope(boat)
local surface = game.surfaces[boat.surface_name]
if not surface then return end
if scope.Data.cannons then
for i = -2, 2 do
local p1 = scope.Data.cannons[1]
local p2 = {x = boat.position.x + p1.x + i * 2, y = boat.position.y + p1.y - 4}
local e = player.surface.create_entity({name = 'gun-turret', position = p2, force = boat.force_name, create_build_effect_smoke = false})
local e = surface.create_entity({name = 'gun-turret', position = p2, force = boat.force_name, create_build_effect_smoke = false})
if e and e.valid then
e.insert({name = "uranium-rounds-magazine", count = 200})
end
@ -1165,7 +1125,7 @@ if _DEBUG then
for i = -2, 2 do
local p1 = scope.Data.cannons[2]
local p2 = {x = boat.position.x + p1.x + i * 2, y = boat.position.y + p1.y + 4}
local e = player.surface.create_entity({name = 'gun-turret', position = p2, force = boat.force_name, create_build_effect_smoke = false})
local e = surface.create_entity({name = 'gun-turret', position = p2, force = boat.force_name, create_build_effect_smoke = false})
if e and e.valid then
e.insert({name = "uranium-rounds-magazine", count = 200})
end
@ -1214,11 +1174,12 @@ if _DEBUG then
player.insert{name='substation', count = 50}
player.insert{name='solar-panel', count = 50}
player.insert{name='submachine-gun', count = 1}
player.insert{name='vehicle-machine-gun', count = 1}
player.insert{name='uranium-rounds-magazine', count = 200}
player.insert{name='raw-fish', count = 100}
player.insert{name='coin', count = 50000}
player.insert{name='rail-signal', count = 300}
player.insert{name='grenade', count = 100}
player.insert{name='steel-chest', count = 50}
end
end)

View File

@ -8,6 +8,8 @@ local Utils = require 'maps.pirates.utils_local'
local CoreData = require 'maps.pirates.coredata'
local Memory = require 'maps.pirates.memory'
local _inspect = require 'utils.inspect'.inspect
local LootRaffle = require 'functions.loot_raffle'
-- local simplex_noise = require 'utils.simplex_noise'.d2
-- local perlin_noise = require 'utils.perlin_noise'
-- local Force_health_booster = require 'modules.force_health_booster'
@ -19,6 +21,7 @@ local Public = {}
-- Public.active_crews_cap = 1
Public.activeCrewsCap = 2
Public.private_run_cap = 1
Public.minimumCapacitySliderValue = 1
Public.minimum_run_capacity_to_enforce_space_for = 22
-- auto-disbanding when there are no players left in the crew:
@ -405,6 +408,17 @@ function Public.is_captain(player)
end
end
function Public.is_officer(player_index)
local memory = Memory.get_crew_memory()
if memory.officers_table and memory.officers_table[player_index] then
return true
else
return false
end
end
-- lifted shamelessly from biter battles, since I haven't done balancing work on this:
function Public.surplus_evo_biter_damage_modifier(surplus_evo)
return Math.floor(surplus_evo/2*1000)/1000 --is this floor needed?
@ -607,7 +621,7 @@ function Public.surface_place_random_obstacle_boxes(surface, center, width, heig
for j = 1, size^2 do
local p2 = surface.find_non_colliding_position('wooden-chest', p, 5, 0.1, true) or p
local e = surface.create_entity{name = 'wooden-chest', position = p2, force = memory.force_name, create_build_effect_smoke = false}
memory.hold_surface_destroyable_wooden_chests[#memory.hold_surface_destroyable_wooden_chests + 1] = e
memory.hold_surface_destroyable_wooden_chests[e.unit_number] = e
e.destructible = false
e.minable = false
e.rotatable = false
@ -1518,4 +1532,77 @@ function Public.is_id_valid(id)
end
end
-- NOTE: Items here are either unobtainable or hard to find/get
-- Connected with crew.lua recipe and technology disables
function Public.get_item_blacklist(tier)
local blacklist = LootRaffle.get_tech_blacklist(tier)
blacklist['landfill'] = true
blacklist['concrete'] = true
blacklist['hazard-concrete'] = true
blacklist['locomotive'] = true
blacklist['cargo-wagon'] = true
blacklist['fluid-wagon'] = true
blacklist['train-stop'] = true
blacklist['rail-signal'] = true
blacklist['rail-chain-signal'] = true
blacklist['refined-concrete'] = true
blacklist['refined-hazard-concrete'] = true
blacklist['flamethrower-turret'] = true
blacklist['tank'] = true
blacklist['cannon-shell'] = true
blacklist['explosive-cannon-shell'] = true
blacklist['speed-module-3'] = true
blacklist['productivity-module-3'] = true
blacklist['effectivity-module-3'] = true
blacklist['space-science-pack'] = true
blacklist['rocket-control-unit'] = true
blacklist['artillery-wagon'] = true
blacklist['artillery-turret'] = true
blacklist['artillery-targeting-remote'] = true
blacklist['uranium-cannon-shell'] = true
blacklist['explosive-uranium-cannon-shell'] = true
blacklist['satellite'] = true
blacklist['rocket-silo'] = true
blacklist['destroyer-capsule'] = true
blacklist['spidertron'] = true
blacklist['discharge-defense-remote'] = true
blacklist['discharge-defense-equipment'] = true
blacklist['express-loader'] = true
blacklist['land-mine'] = true
blacklist['wood'] = true -- too easy to acquire
return blacklist
end
-- tier: affects amount of items and rarity returned
-- scale: final result of formula with tier scaled
-- tech_tier: float in range [0; 1]; 1 = everything unlocked
function Public.pick_random_price(tier, scale, tech_tier)
if tier < 0 or scale < 0 then return end
local item_stacks = LootRaffle.roll(math.floor(scale * (tier ^ 2 + 10 * tier)), 100, Public.get_item_blacklist(tech_tier))
local price = {}
for _, item_stack in pairs(item_stacks) do
price[#price+1] = {name = item_stack.name, amount = item_stack.count}
end
return price
end
-- This method should exist in table but it doesn't for some reason on comfy repo so I copied it to here
function Public.get_random_dictionary_entry(t, key)
local target_index = Math.random(1, table_size(t))
local count = 1
for k, v in pairs(t) do
if target_index == count then
if key then
return k
else
return v
end
end
count = count + 1
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.3.5' --major.minor.patch versioning, to match factorio mod portal
Public.version_string = '1.4.1' --major.minor.patch versioning, to match factorio mod portal
Public.blueprint_library_allowed = true
Public.blueprint_importing_allowed = true
@ -20,6 +20,8 @@ Public.total_max_biters = 2000
Public.lobby_surface_name = '000-000-Lobby'
Public.private_run_lock_amount_hr = 24 -- how many hours need to pass, when crew is empty or inactive, until private run becomes public
Public.colors = {
coal = {r=0.5, g=0.5, b=0.5},
wood = {r=204, g=158, b=67},
@ -84,18 +86,20 @@ Public.unteleportable_names = {'transport-belt', 'underground-belt', 'splitter',
Public.comfy_emojis = {
monkas = '<:monkas:555120573752279056>',
-- monkas = '<:monkas:555120573752279056>', -- deprecated, all occurences replaced with despair
despair = '<:despair:1004858546044805241>',
trashbin = '<:trashbin:835887736253710396>',
pogkot = '<:pogkot:763854655612518420>',
goldenobese = '<:goldenobese:491135683508043786>',
wut = '<:wut:493320605592977443>',
smolfish = '<:smolfish:673942701682589731>',
mjau = '<:mjau:789611417132073010>',
-- wut = '<:wut:493320605592977443>', -- deprecated, all occurences replaced with hype
hype = '<:hype:1024006040624308274>',
-- smolfish = '<:smolfish:673942701682589731>', -- deprecated, all occurences replaced with hype
-- mjau = '<:mjau:789611417132073010>', -- deprecated, all occurences replaced with hype
spurdo = '<:spurdo:669546779360100382>',
loops = '<:loops:783508194755346462>',
ree1 = '<:ree1:555118905090244618>',
derp = '<:derp:527570293850505266>',
doge = '<:doge:491152224681066496>',
derp = '<:derp:1024006042360742028>',
-- doge = '<:doge:491152224681066496>', -- deprecated
yum1 = '<:yum1:740341272451219517>',
feel = '<:feel:491147760553164800>',
kewl = '<:kewl:837016976937189418>',

View File

@ -11,6 +11,8 @@ local CoreData = require 'maps.pirates.coredata'
local Server = require 'utils.server'
local Utils = require 'maps.pirates.utils_local'
local Surfaces = require 'maps.pirates.surfaces.surfaces'
local Islands = require 'maps.pirates.surfaces.islands.islands'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
-- local Structures = require 'maps.pirates.structures.structures'
local Boats = require 'maps.pirates.structures.boats.boats'
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
@ -130,11 +132,11 @@ function Public.try_lose(loss_reason)
local playtimetext = Utils.time_longform((memory.age or 0)/60)
local message = {'',loss_reason,' ',{'pirates.loss_rest_of_message_long', playtimetext, Public.get_crewmembers_printable_string()}}
local message = {'',loss_reason,' ',{'pirates.loss_rest_of_message_long', playtimetext, memory.overworldx, Public.get_crewmembers_printable_string()}}
Server.to_discord_embed_raw({'',CoreData.comfy_emojis.trashbin .. '[' .. memory.name .. '] ', message}, true)
local message2 = {'',loss_reason,' ',{'pirates.loss_rest_of_message_short', '[font=default-large-semibold]' .. playtimetext .. '[/font]'}}
local message2 = {'',loss_reason,' ',{'pirates.loss_rest_of_message_short', '[font=default-large-semibold]' .. playtimetext .. '[/font]', memory.overworldx}}
Common.notify_game({'', '[' .. memory.name .. '] ',message2}, CoreData.colors.notify_gameover)
@ -488,7 +490,7 @@ function Public.plank(captain, player)
if Utils.contains(Common.crew_get_crew_members(), player) then
if (not (captain.index == player.index)) then
Server.to_discord_embed_raw(CoreData.comfy_emojis.monkas .. string.format("%s planked %s!", captain.name, player.name))
Server.to_discord_embed_raw(CoreData.comfy_emojis.despair .. string.format("%s planked %s!", captain.name, player.name))
Common.notify_force(player.force, {'pirates.plank', captain.name, player.name})
@ -525,7 +527,7 @@ function Public.disband_crew(donotprint)
local message = {'pirates.crew_disband', memory.name, Utils.time_longform((memory.real_age or 0)/60)}
Common.notify_game(message)
Server.to_discord_embed_raw({'', CoreData.comfy_emojis.monkas, message}, true)
Server.to_discord_embed_raw({'', CoreData.comfy_emojis.despair, message}, true)
-- if memory.game_won then
-- game.print({'chronosphere.message_game_won_restart'}, {r=0.98, g=0.66, b=0.22})
@ -533,6 +535,7 @@ function Public.disband_crew(donotprint)
end
memory.game_lost = true -- only necessary to avoid printing research notifications
Public.reset_crew_and_enemy_force(id)
local lobby = game.surfaces[CoreData.lobby_surface_name]
@ -589,7 +592,11 @@ function Public.disband_crew(donotprint)
if game.surfaces[crowsnestname] then game.delete_surface(game.surfaces[crowsnestname]) end
for _, destination in pairs(memory.destinations) do
if game.surfaces[destination.surface_name] then game.delete_surface(game.surfaces[destination.surface_name]) end
if game.surfaces[destination.surface_name] then
game.delete_surface(game.surfaces[destination.surface_name])
end
Islands[IslandEnum.enum.CAVE].cleanup_cave_surface(destination)
end
global_memory.crew_memories[id] = nil
@ -715,6 +722,9 @@ function Public.initialise_crew(accepted_proposal)
memory.difficulty = CoreData.difficulty_options[accepted_proposal.difficulty_option].value
memory.capacity = CoreData.capacity_options[accepted_proposal.capacity_option].value
-- memory.mode = CoreData.mode_options[accepted_proposal.mode_option].value
memory.run_is_private = accepted_proposal.run_is_private
memory.private_run_password = accepted_proposal.private_run_password
memory.private_run_lock_timer = 60 * 60 * 60 * CoreData.private_run_lock_amount_hr
memory.destinationsvisited_indices = {}
memory.stored_fuel = Balance.starting_fuel
@ -748,6 +758,7 @@ function Public.initialise_crew(accepted_proposal)
memory.overworldy = 0
memory.hold_surface_destroyable_wooden_chests = {}
memory.hold_surface_timers_of_wooden_chests_queued_for_destruction = {}
memory.seaname = SurfacesCommon.encode_surface_name(memory.id, 0, SurfacesCommon.enum.SEA, enum.DEFAULT)
@ -796,7 +807,7 @@ function Public.summon_crew()
end
end
-- NOTE: Connected with common.lua item blacklist
function Public.reset_crew_and_enemy_force(id)
local crew_force = game.forces[Common.get_crew_force_name(id)]
local enemy_force = game.forces[Common.get_enemy_force_name(id)]
@ -876,40 +887,16 @@ function Public.reset_crew_and_enemy_force(id)
--as prerequisites for uranium ammo and automation 3:
crew_force.technologies['speed-module'].researched = true
crew_force.technologies['tank'].researched = true
crew_force.recipes['speed-module'].enabled = false
crew_force.recipes['tank'].enabled = false
crew_force.recipes['cannon-shell'].enabled = false
crew_force.recipes['explosive-cannon-shell'].enabled = false
crew_force.technologies['concrete'].researched = true
--@TRYING this out:
crew_force.technologies['coal-liquefaction'].enabled = true
crew_force.technologies['coal-liquefaction'].researched = true
crew_force.technologies['automobilism'].enabled = false
crew_force.technologies['toolbelt'].enabled = false --trying this. we don't actually want players to carry too many things manually, and in fact in a resource-tight scenario that's problematic
-- note: many of these recipes are overwritten after tech researched!!!!!!! like pistol. check elsewhere in code
crew_force.recipes['pistol'].enabled = false
-- these are redundant I think...?:
crew_force.recipes['centrifuge'].enabled = false
crew_force.recipes['flamethrower-turret'].enabled = false
crew_force.technologies['railway'].researched = true --needed for purple sci
crew_force.recipes['rail'].enabled = true --needed for purple sci
crew_force.recipes['locomotive'].enabled = false
crew_force.recipes['car'].enabled = false
crew_force.recipes['cargo-wagon'].enabled = false
crew_force.recipes['nuclear-fuel'].enabled = false -- reduce clutter
-- crew_force.recipes['underground-belt'].enabled = false
-- crew_force.recipes['fast-underground-belt'].enabled = false
-- crew_force.recipes['express-underground-belt'].enabled = false
crew_force.technologies['land-mine'].enabled = false
crew_force.technologies['landfill'].enabled = false
@ -920,7 +907,6 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.technologies['logistic-system'].enabled = false
crew_force.technologies['tank'].enabled = false
crew_force.technologies['rocketry'].enabled = false
crew_force.technologies['artillery'].enabled = false
crew_force.technologies['destroyer'].enabled = false
@ -982,8 +968,7 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.technologies['steel-axe'].enabled = false
crew_force.technologies['concrete'].enabled = false
crew_force.technologies['nuclear-power'].enabled = false
crew_force.technologies['nuclear-power'].enabled = true
crew_force.technologies['effect-transmission'].enabled = true
@ -995,7 +980,7 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.technologies['speed-module'].enabled = true
crew_force.technologies['speed-module-2'].enabled = false
crew_force.technologies['speed-module-3'].enabled = false
crew_force.technologies['effectivity-module'].enabled = false
crew_force.technologies['effectivity-module'].enabled = true
crew_force.technologies['effectivity-module-2'].enabled = false
crew_force.technologies['effectivity-module-3'].enabled = false
crew_force.technologies['automation-3'].enabled = true
@ -1004,7 +989,7 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.technologies['space-science-pack'].enabled = false
crew_force.technologies['mining-productivity-4'].enabled = false
crew_force.technologies['logistics-3'].enabled = true
crew_force.technologies['nuclear-fuel-reprocessing'].enabled = false
crew_force.technologies['nuclear-fuel-reprocessing'].enabled = true
-- crew_force.technologies['railway'].enabled = false
crew_force.technologies['automated-rail-transportation'].enabled = false
@ -1040,7 +1025,33 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.technologies['distractor'].enabled = false
crew_force.technologies['military-4'].enabled = true
crew_force.technologies['uranium-ammo'].enabled = true
Public.disable_recipes(crew_force)
end
-- NOTE: Connected with common.lua item blacklist
function Public.disable_recipes(crew_force)
crew_force.recipes['pistol'].enabled = false
-- crew_force.recipes['centrifuge'].enabled = false
-- crew_force.recipes['flamethrower-turret'].enabled = false
crew_force.recipes['locomotive'].enabled = false
-- crew_force.recipes['car'].enabled = false
crew_force.recipes['cargo-wagon'].enabled = false
crew_force.recipes['slowdown-capsule'].enabled = false
-- crew_force.recipes['nuclear-fuel'].enabled = false
-- crew_force.recipes['rail'].enabled = false
crew_force.recipes['speed-module'].enabled = false
crew_force.recipes['tank'].enabled = false
crew_force.recipes['cannon-shell'].enabled = false
crew_force.recipes['explosive-cannon-shell'].enabled = false
-- and since we can't build tanks anyway, let's disable this for later:
crew_force.recipes['uranium-cannon-shell'].enabled = false
crew_force.recipes['explosive-uranium-cannon-shell'].enabled = false
crew_force.recipes['concrete'].enabled = false
crew_force.recipes['hazard-concrete'].enabled = false
crew_force.recipes['refined-concrete'].enabled = false
crew_force.recipes['refined-hazard-concrete'].enabled = false
end
return Public

View File

@ -235,6 +235,9 @@ end
function Public.click(event)
if not event.element then return end
if not event.element.valid then return end
local player = game.players[event.element.player_index]
if not player.gui.screen[window_name .. '_piratewindow'] then return end

View File

@ -14,6 +14,13 @@ local Public = {}
local window_name = 'crew'
local function get_selected_player_index(flow)
if flow.members.body.members_listbox.selected_index ~= 0 then
return tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])
else
return nil
end
end
function Public.toggle_window(player)
local memory = Memory.get_crew_memory()
@ -318,18 +325,20 @@ function Public.full_update(player)
flow.difficulty_vote.visible = memory.overworldx and memory.overworldx == 0
flow.members.body.officer_resign.visible = memory.officers_table and memory.officers_table[player.index]
flow.members.body.officer_resign.visible = Common.is_officer(player.index)
local other_player_selected = flow.members.body.members_listbox.selected_index ~= 0 and tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2]) ~= player.index
local selected_player_index = get_selected_player_index(flow)
local other_player_selected = flow.members.body.members_listbox.selected_index ~= 0 and selected_player_index ~= player.index
flow.captain.visible = Common.is_captain(player)
flow.undock_tip.visible = Common.is_captain(player)
flow.captain.body.capn_pass.visible = other_player_selected
flow.captain.body.capn_plank.visible = flow.captain.body.capn_pass.visible
flow.captain.body.capn_plank.visible = other_player_selected
flow.captain.body.make_officer.visible = other_player_selected and (not (memory.officers_table and memory.officers_table[tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])]))
flow.captain.body.unmake_officer.visible = other_player_selected and ((memory.officers_table and memory.officers_table[tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])]))
flow.captain.body.make_officer.visible = other_player_selected and (not Common.is_officer(selected_player_index))
flow.captain.body.unmake_officer.visible = other_player_selected and Common.is_officer(selected_player_index)
-- flow.captain.body.capn_undock_normal.visible = memory.boat and memory.boat.state and ((memory.boat.state == Boats.enum_state.LANDED) or (memory.boat.state == Boats.enum_state.APPROACHING) or (memory.boat.state == Boats.enum_state.DOCKED))
@ -403,6 +412,9 @@ end
function Public.click(event)
-- This is only needed since we call click on every single GUI element and if element gets destroyed, it's no good (these checks wouldn't be needed (I think) if GUI was purely event driven)
if not event.element then return end
if not event.element.valid then return end
local player = game.players[event.element.player_index]
@ -502,25 +514,25 @@ function Public.click(event)
end
if eventname == 'capn_pass' then
local other_id = tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])
local other_id = get_selected_player_index(flow)
Roles.pass_captainhood(player, game.players[other_id])
return
end
if eventname == 'make_officer' then
local other_id = tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])
local other_id = get_selected_player_index(flow)
Roles.make_officer(player, game.players[other_id])
return
end
if eventname == 'unmake_officer' then
local other_id = tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])
local other_id = get_selected_player_index(flow)
Roles.unmake_officer(player, game.players[other_id])
return
end
if eventname == 'capn_plank' then
local other_id = tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])
local other_id = get_selected_player_index(flow)
Crew.plank(player, game.players[other_id])
return

View File

@ -175,6 +175,8 @@ end
function Public.click(event)
if not event.element then return end
if not event.element.valid then return end
local player = game.players[event.element.player_index]

View File

@ -26,6 +26,7 @@ local Surfaces = require 'maps.pirates.surfaces.surfaces'
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 ComfyGui = require 'utils.gui'
ComfyGui.set_disabled_tab('Scoreboard', true)
@ -565,7 +566,7 @@ function Public.process_etaframe_update(player, flow1, bools)
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 == Surfaces.Island.enum.MAZE then
elseif destination.type == Surfaces.enum.ISLAND and destination.subtype == IslandEnum.enum.MAZE then
total = Common.map_loading_ticks_atsea_maze
end
@ -876,6 +877,12 @@ function Public.process_siloframe_and_questframe_updates(flowsilo, flowquest, bo
flow1.quest_label_3.caption = {'pirates.gui_questframe_fail'}
flow1.quest_label_3.style.font_color = GuiCommon.insufficient_font_color
end
elseif quest_type == Quest.enum.FISH then
if tooltip == '' then tooltip = {'pirates.gui_questframe_fish'} end
elseif quest_type == Quest.enum.COMPILATRON then
if tooltip == '' then tooltip = {'pirates.gui_questframe_compilatron'} end
end
end

View File

@ -186,6 +186,8 @@ end
function Public.click(event)
if not event.element then return end
if not event.element.valid then return end
local player = game.players[event.element.player_index]
-- local name = 'info'

View File

@ -149,6 +149,8 @@ end
function Public.click(event)
if not event.element then return end
if not event.element.valid then return end
local player = game.players[event.element.player_index]

View File

@ -163,13 +163,24 @@ end
function Public.toggle_window(player)
local window
local flow, flow2, flow3, flow4, flow5
--*** OVERALL FLOW ***--
if player.gui.screen[window_name .. '_piratewindow'] then player.gui.screen[window_name .. '_piratewindow'].destroy() return end
flow = GuiCommon.new_window(player, window_name)
flow.caption = {'pirates.gui_runs_play'}
window = GuiCommon.new_window(player, window_name)
window.caption = {'pirates.gui_runs_play'}
flow = window.add {
type = 'scroll-pane',
name = 'scroll_pane',
direction = 'vertical',
horizontal_scroll_policy = 'never',
vertical_scroll_policy = 'auto'
}
flow.style.maximal_height = 500
flow.style.bottom_padding = 20
--*** ONGOING RUNS ***--
@ -191,6 +202,25 @@ function Public.toggle_window(player)
flow3.style.margin = 2
flow3.style.horizontally_stretchable = true
flow3 = flow2.add({
name = 'join_crew_info',
type = 'label',
caption = {'pirates.gui_join_private_run_info', 0, 0, 0},
visible = false,
})
flow3.style.single_line = false
flow3 = flow2.add({
name = 'password_namefield',
type = 'textfield',
text = '',
visible = false,
})
flow3.style.width = 150
flow3.style.height = 24
flow3.style.top_margin = -3
flow3.style.bottom_margin = 3
flow3 = flow2.add({
name = 'flow_buttons',
type = 'flow',
@ -314,6 +344,52 @@ function Public.toggle_window(player)
flow5.style.top_margin = -3
flow5.style.bottom_margin = 3
-- PRIVATE RUN ELEMENTS --
flow4.add({
name = 'private_checkbox',
type = 'checkbox',
caption = {'pirates.gui_runs_proposal_maker_private'},
state = false,
tooltip = {'pirates.gui_runs_proposal_maker_private_tooltip', CoreData.private_run_lock_amount_hr}
})
flow5 = flow4.add({
name = 'password_label',
type = 'label',
caption = {'pirates.gui_runs_proposal_maker_password'},
})
flow5.style.font = 'heading-3'
flow5 = flow4.add({
name = 'password_namefield',
type = 'textfield',
text = '',
})
flow5.style.width = 150
flow5.style.height = 24
flow5.style.top_margin = -3
flow5.style.bottom_margin = 3
flow5 = flow4.add({
name = 'confirm_password_label',
type = 'label',
caption = {'pirates.gui_runs_proposal_maker_confirm_password'},
})
flow5.style.font = 'heading-3'
flow5 = flow4.add({
name = 'confirm_password_namefield',
type = 'textfield',
text = '',
})
flow5.style.width = 150
flow5.style.height = 24
flow5.style.top_margin = -3
flow5.style.bottom_margin = 3
-- CREW SIZE LIMIT SLIDER --
flow5 = flow4.add({
name = 'options',
type = 'table',
@ -415,7 +491,7 @@ function Public.full_update(player)
local memory = Memory.get_crew_memory()
if not player.gui.screen['runs_piratewindow'] then return end
local flow = player.gui.screen['runs_piratewindow']
local flow = player.gui.screen['runs_piratewindow'].scroll_pane
local playercrew_status = GuiCommon.crew_overall_state_bools(player.index)
if not playercrew_status then return end
@ -448,6 +524,12 @@ function Public.full_update(player)
if not selected_joinable_bool then flow.ongoing_runs.body.ongoing_runs_listbox.selected_index = 0 end
flow.ongoing_runs.body.leaving_prompt.visible = playercrew_status.leaving
local show_password_info = crewid and global_memory.crew_memories[crewid].run_is_private
flow.ongoing_runs.body.join_crew_info.visible = show_password_info
flow.ongoing_runs.body.password_namefield.visible = show_password_info
end
flow.proposals.visible = (memory.crewstatus == nil and not playercrew_status.leaving)
@ -485,6 +567,11 @@ function Public.full_update(player)
flow.proposals.body.flow_proposal_launch.launch_crew.visible = playercrew_status.proposal_can_launch
local checkbox_state = flow.proposals.body.proposal_maker.body.private_checkbox.state
flow.proposals.body.proposal_maker.body.password_label.visible = checkbox_state
flow.proposals.body.proposal_maker.body.password_namefield.visible = checkbox_state
flow.proposals.body.proposal_maker.body.confirm_password_label.visible = checkbox_state
flow.proposals.body.proposal_maker.body.confirm_password_namefield.visible = checkbox_state
end
@ -504,6 +591,21 @@ function Public.full_update(player)
-- wrappedmemories[#wrappedmemories + 1] = {'pirates.run_displayform', mem.id, mem.name, Utils.spritepath_to_richtext(CoreData.difficulty_options[mem.difficulty_option].icon), count, CoreData.capacity_options[mem.capacity_option].text2, ' [item=rail] ', mem.overworldx or 0}
end
GuiCommon.update_listbox(flow.ongoing_runs.body.ongoing_runs_listbox, wrappedmemories)
local crewid = nil
local bool1 = (not playercrew_status.leaving) and (not playercrew_status.adventuring) and (not playercrew_status.spectating) and (flow.ongoing_runs.body.ongoing_runs_listbox.selected_index ~= 0)
if bool1 then
crewid = tonumber((flow.ongoing_runs.body.ongoing_runs_listbox.get_item(flow.ongoing_runs.body.ongoing_runs_listbox.selected_index))[2])
end
-- Update timer when run will become public
if crewid and flow.ongoing_runs.body.join_crew_info.visible then
local lock_timer = global_memory.crew_memories[crewid].private_run_lock_timer
local sec = Math.floor((lock_timer / (60)) % 60)
local min = Math.floor((lock_timer / (60 * 60)) % 60)
local hrs = Math.floor((lock_timer / (60 * 60 * 60)) % 60)
flow.ongoing_runs.body.join_crew_info.caption = {'pirates.gui_join_private_run_info', hrs, min, sec}
end
end
if flow.proposals.visible then
@ -542,18 +644,19 @@ function Public.full_update(player)
-- end
-- end
end
end
function Public.click(event)
if not event.element then return end
if not event.element.valid then return end
local player = game.players[event.element.player_index]
local eventname = event.element.name
if not player.gui.screen[window_name .. '_piratewindow'] then return end
local flow = player.gui.screen[window_name .. '_piratewindow']
local flow = player.gui.screen[window_name .. '_piratewindow'].scroll_pane
local global_memory = Memory.get_global_memory()
-- local memory = Memory.get_crew_memory()
@ -573,12 +676,56 @@ function Public.click(event)
if eventname == 'join_crew' then
local listbox = flow.ongoing_runs.body.ongoing_runs_listbox
local crewid = tonumber(listbox.get_item(listbox.selected_index)[2])
-- If run is private
if global_memory.crew_memories[crewid].run_is_private then
if global_memory.crew_memories[crewid].private_run_password == flow.ongoing_runs.body.password_namefield.text then
Crew.join_crew(player, crewid)
flow.ongoing_runs.body.join_crew_info.visible = false
flow.ongoing_runs.body.password_namefield.visible = false
else
Common.notify_player_error(player, {'pirates.gui_join_private_run_error_wrong_password'})
end
else
Crew.join_crew(player, crewid)
end
Crew.join_crew(player, tonumber(listbox.get_item(listbox.selected_index)[2]))
return
end
if eventname == 'propose_crew' then
-- If proposal was set as private
local run_is_private = flow.proposals.body.proposal_maker.body.private_checkbox.state
if run_is_private then
-- Count private runs
local private_run_count = 0
for _, id in pairs(global_memory.crew_active_ids) do
if global_memory.crew_memories[id].run_is_private then
private_run_count = private_run_count + 1
end
end
-- Make sure private run can be created
if private_run_count >= global_memory.private_run_cap then
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_private_run_limit'})
return
end
-- Check if passwords match
if flow.proposals.body.proposal_maker.body.password_namefield.text ~= flow.proposals.body.proposal_maker.body.confirm_password_namefield.text then
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_private_run_password_no_match'})
return
end
-- Check if passwords aren't empty
if flow.proposals.body.proposal_maker.body.password_namefield.text == '' then
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_private_run_password_empty'})
return
end
end
local private_run_password = flow.proposals.body.proposal_maker.body.password_namefield.text
local proposal_name = flow.proposals.body.proposal_maker.body.namefield.text
-- local proposal_name = string.sub(flow.proposals.body.proposal_maker.body.namefield.text, 1, 30)
@ -626,14 +773,19 @@ function Public.click(event)
capacity_option = capacity_option,
-- mode_option = mode_option,
endorserindices = {player.index},
run_is_private = run_is_private,
private_run_password = private_run_password,
}
global_memory.crewproposals[#global_memory.crewproposals + 1] = proposal
local message = {'pirates.proposal_propose', player.name, proposal_name, CoreData.capacity_options[capacity_option].text3}
if run_is_private then
Common.notify_lobby({'pirates.proposal_propose_private', player.name, proposal_name, CoreData.capacity_options[capacity_option].text3})
else
Common.notify_lobby({'pirates.proposal_propose', player.name, proposal_name, CoreData.capacity_options[capacity_option].text3})
end
-- local message = player.name .. ' proposed the run ' .. proposal_name .. ' (difficulty ' .. CoreData.difficulty_options[difficulty_option].text .. ', capacity ' .. CoreData.capacity_options[capacity_option].text3 .. ').'
Common.notify_lobby(message)
return
end
@ -669,6 +821,22 @@ function Public.click(event)
if GuiCommon.crew_overall_state_bools(player.index).proposal_can_launch then --double check
for k, proposal in pairs(global_memory.crewproposals) do
if #proposal.endorserindices > 0 and proposal.endorserindices[1] == player.index then
-- Make sure private run can be created
if proposal.run_is_private then
-- NOTE: I didn't want to add this check in "proposal_can_launch", because different error message would get displayed (I think?).
local private_run_count = 0
for _, id in pairs(global_memory.crew_active_ids) do
if global_memory.crew_memories[id].run_is_private then
private_run_count = private_run_count + 1
end
end
if private_run_count >= global_memory.private_run_cap then
Common.notify_player_error(player, {'pirates.gui_runs_proposal_maker_error_private_run_limit'})
return
end
end
Crew.initialise_crew(proposal)
global_memory.crewproposals[k] = nil
Progression.set_off_from_starting_dock()

View File

@ -528,12 +528,10 @@ end
local score_gui_token = Token.register(score_gui)
local function on_gui_click(event)
local element = event.element
if not element or not element.valid then
return
end
if not event.element then return end
if not event.element.valid then return end
local player = game.get_player(element.player_index)
local player = game.get_player(event.element.player_index)
local frame = Gui.get_player_active_frame(player)
if not frame then

View File

@ -3,7 +3,7 @@
local Math = require 'maps.pirates.math'
-- local Memory = require 'maps.pirates.memory'
-- local Balance = require 'maps.pirates.balance'
local Balance = require 'maps.pirates.balance'
-- local CoreData = require 'maps.pirates.coredata'
local Common = require 'maps.pirates.common'
local _inspect = require 'utils.inspect'.inspect
@ -51,6 +51,8 @@ Public.chest_loot_data_raw = {
{12, 0, 1, false, 'artillery-shell', 1, 1},
{4, 0, 0.8, false, 'pistol', 1, 3},
{3, 0, 0.2, false, 'storage-tank', 2, 4},
{2, 0.1, 1, false, 'explosives', 5, 9},
{2, 0.2, 1, false, 'cliff-explosives', 2, 4},
{0.25, 0, 0.5, false, 'uranium-238', 5, 8},
{8, 0, 1.2, true, 'steel-chest', 4, 12},
@ -308,15 +310,16 @@ end
function Public.swamp_storage_tank_fluid_loot()
local ret
ret = {name = 'sulfuric-acid', amount = 100*Math.ceil(Math.random(5^2, 40^2)^(1/2))}
-- ret = {name = 'sulfuric-acid', amount = 100*Math.ceil(Math.random(5^2, 40^2)^(1/2))} -- don't know why this formula made best amount most common, but lowest amount least common (was this intentional?).
ret = {name = 'sulfuric-acid', amount = 100*Math.ceil(Math.random(10, 40) * Balance.island_richness_avg_multiplier())}
return ret
end
function Public.roboport_bots_loot()
return {
{name = 'logistic-robot', count = 8},
{name = 'logistic-robot', count = Math.ceil((10 + Math.random(5)) * Balance.island_richness_avg_multiplier())},
{name = 'construction-robot', count = Math.ceil((5 + Math.random(5)) * Balance.island_richness_avg_multiplier())},
}
-- construction robots
end
function Public.random_plates(multiplier)
@ -354,7 +357,7 @@ function Public.maze_camp_loot()
end
end
Public.maze_lab_loot_data_raw = {
Public.lab_loot_data_raw = {
{8, -0.5, 0.5, true, 'automation-science-pack', 5, 20},
{8, -0.6, 0.6, true, 'logistic-science-pack', 5, 20},
{6, -0.1, 1, true, 'military-science-pack', 5, 18},
@ -365,8 +368,8 @@ Public.maze_lab_loot_data_raw = {
-- {10, 0.5, 1.5, true, 'space-science-pack', 16, 32},
}
function Public.maze_lab_loot()
return Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.maze_lab_loot_data_raw), 1, Math.clamp(0, 1, Math.sloped(Common.difficulty_scale(),1/2) * (Common.game_completion_progress())))
function Public.lab_loot()
return Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.lab_loot_data_raw), 1, Math.clamp(0, 1, Math.sloped(Common.difficulty_scale(),1/2) * (Common.game_completion_progress())))
end
Public.maze_treasure_data_raw = {

View File

@ -110,6 +110,8 @@ local function on_init()
Common.init_game_settings(Balance.technology_price_multiplier)
global_memory.active_crews_cap = Common.activeCrewsCap
global_memory.private_run_cap = Common.private_run_cap
global_memory.minimumCapacitySliderValue = Common.minimumCapacitySliderValue
Surfaces.Lobby.create_starting_dock_surface()
@ -123,6 +125,8 @@ local function on_init()
game.create_force(Common.get_ancient_friendly_force_name(id))
game.create_force(Common.get_ancient_hostile_force_name(id))
game.create_force(Common.get_crew_force_name(id))
Crew.reset_crew_and_enemy_force(id)
end
@ -182,6 +186,7 @@ local function crew_tick()
PiratesApiOnTick.check_for_cliff_explosives_in_hold_wooden_chests()
PiratesApiOnTick.equalise_fluid_storages() -- Made the update less often for small performance gain, but frequency can be increased if players complain
PiratesApiOnTick.revealed_buried_treasure_distance_check()
PiratesApiOnTick.update_private_run_lock_timer(60)
PiratesApiOnTick.victory_continue_reminder()
Kraken.overall_kraken_tick()

View File

@ -13,7 +13,57 @@ local simplex_noise = require 'utils.simplex_noise'.d2
local Public = {}
-- Gives less and less ore with every call, until given amount slowly converges to 1
-- For now used just for Cave island to give players ore when mining rocks
-- NOTE: Also gives some coins
function Public.try_give_ore(player, realp, source_name)
local destination = Common.current_destination()
local choices = destination.dynamic_data.hidden_ore_remaining_abstract
if choices and Utils.length(choices) > 0 then
local choices_possible = {}
local choices_to_prioitise = {}
local total_ore_left = 0
for k, v in pairs(choices) do
if v>0 then choices_possible[k] = v end
total_ore_left = total_ore_left + v
if (not destination.dynamic_data.ore_types_spawned[k]) then
choices_to_prioitise[#choices_to_prioitise + 1] = k
end
end
if Utils.length(choices_possible) > 0 then
local choice
if Utils.length(choices_to_prioitise) > 0 then
choice = choices_to_prioitise[Math.random(Utils.length(choices_to_prioitise))]
else
choice = Raffle.raffle2(choices_possible)
end
if not choice then return end
local coin_amount = 4 + Math.random(4)
local real_amount = Math.max(Common.minimum_ore_placed_per_tile, Common.ore_abstract_to_real(total_ore_left))
local given_amount = Math.ceil(real_amount * Math.random_float_in_range(0.004, 0.006))
if source_name == 'rock-huge' then
given_amount = given_amount * 1.5
coin_amount = coin_amount * 2
end
local to_give = {}
to_give[#to_give+1] = {name = choice, count = Math.ceil(given_amount)}
to_give[#to_give+1] = {name = 'coin', count = Math.ceil(coin_amount)}
Common.give(player, to_give, realp)
choices[choice] = Math.max(0, choices[choice] - Common.ore_real_to_abstract(given_amount))
end
end
end
function Public.try_ore_spawn(surface, realp, source_name, density_bonus)
density_bonus = density_bonus or 0
@ -65,6 +115,8 @@ function Public.try_ore_spawn(surface, realp, source_name, density_bonus)
ret = true
end
else
if not choice then return false end
local real_amount = Math.max(Common.minimum_ore_placed_per_tile, Common.ore_abstract_to_real(choices[choice]))
local density = (density_bonus + 17 + 4 * Math.random()) -- not too big, and not too much variation; it makes players have to stay longer

View File

@ -8,7 +8,7 @@ local Balance = require 'maps.pirates.balance'
local Common = require 'maps.pirates.common'
local CoreData = require 'maps.pirates.coredata'
local Utils = require 'maps.pirates.utils_local'
local _inspect = require 'utils.inspect'.inspect
-- local _inspect = require 'utils.inspect'.inspect
-- local Server = require 'utils.server'
-- local Structures = require 'maps.pirates.structures.structures'
@ -16,7 +16,7 @@ local Boats = require 'maps.pirates.structures.boats.boats'
local Surfaces = require 'maps.pirates.surfaces.surfaces'
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
local Dock = require 'maps.pirates.surfaces.dock'
-- local Islands = require 'maps.pirates.surfaces.islands.islands'
local Islands = require 'maps.pirates.surfaces.islands.islands'
-- local Sea = require 'maps.pirates.surfaces.sea.sea'
local Crew = require 'maps.pirates.crew'
-- local Roles = require 'maps.pirates.roles.roles'
@ -30,24 +30,26 @@ local Upgrades = require 'maps.pirates.boat_upgrades'
local Kraken = require 'maps.pirates.surfaces.sea.kraken'
local Highscore = require 'maps.pirates.highscore'
local CustomEvents = require 'maps.pirates.custom_events'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local NIL = 'none'
local DOCK = 'dock'
local FIRST = Surfaces.Island.enum.FIRST
local RED_DESERT = Surfaces.Island.enum.RED_DESERT
local SWAMP = Surfaces.Island.enum.SWAMP
local STANDARD = Surfaces.Island.enum.STANDARD
local WALKWAYS = Surfaces.Island.enum.WALKWAYS
local MAZE = Surfaces.Island.enum.MAZE
local RADIOACTIVE = Surfaces.Island.enum.RADIOACTIVE
local HORSESHOE = Surfaces.Island.enum.HORSESHOE
local STANDARD_VARIANT = Surfaces.Island.enum.STANDARD_VARIANT
local FIRST = IslandEnum.enum.FIRST
local RED_DESERT = IslandEnum.enum.RED_DESERT
local SWAMP = IslandEnum.enum.SWAMP
local STANDARD = IslandEnum.enum.STANDARD
local WALKWAYS = IslandEnum.enum.WALKWAYS
local MAZE = IslandEnum.enum.MAZE
local RADIOACTIVE = IslandEnum.enum.RADIOACTIVE
local HORSESHOE = IslandEnum.enum.HORSESHOE
local STANDARD_VARIANT = IslandEnum.enum.STANDARD_VARIANT
local CAVE = IslandEnum.enum.CAVE
local A = {STANDARD_VARIANT, RED_DESERT, HORSESHOE, WALKWAYS}
local B = {NIL, NIL, NIL, STANDARD, STANDARD_VARIANT, RED_DESERT, HORSESHOE, WALKWAYS}
local B = {NIL, NIL, NIL, STANDARD, STANDARD_VARIANT, RED_DESERT, HORSESHOE, WALKWAYS, CAVE}
local C = {STANDARD, STANDARD_VARIANT, RED_DESERT, HORSESHOE, WALKWAYS}
local D = {NIL, NIL, NIL, STANDARD, STANDARD_VARIANT, RED_DESERT, HORSESHOE, WALKWAYS, SWAMP}
local D = {NIL, NIL, NIL, STANDARD, STANDARD_VARIANT, RED_DESERT, HORSESHOE, WALKWAYS, SWAMP, CAVE}
local destinationScheme = {
[0] = {DOCK, FIRST, NIL},
@ -225,7 +227,7 @@ function Public.generate_destination_base_cost_to_undock(p, subtype)
end
end
-- override:
if subtype == Surfaces.Island.enum.RADIOACTIVE then
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
@ -347,20 +349,33 @@ function Public.generate_overworld_destination(p)
-- end
boat_for_sale_type = Boats.enum.SLOOP
local upgrade_for_sale
if macro_p.x == 0 then
upgrade_for_sale = nil
elseif macro_p.x == 3 then
upgrade_for_sale = Upgrades.enum.MORE_POWER
elseif macro_p.x == 7 then
upgrade_for_sale = Upgrades.enum.EXTRA_HOLD
elseif macro_p.x % 16 < 8 then
upgrade_for_sale = Upgrades.enum.MORE_POWER
else
upgrade_for_sale = Upgrades.enum.EXTRA_HOLD
end --upgrades like UNLOCK_MERCHANTS will slot themselves in when necessary, due to .overwrite_a_dock_upgrade()
local upgrade_for_sale = nil
-- These upgrades have been made to be exclusive purchase at captain's cabin
-- local upgrade_for_sale
-- if macro_p.x == 0 then
-- upgrade_for_sale = nil
-- elseif macro_p.x == 3 then
-- upgrade_for_sale = Upgrades.enum.MORE_POWER
-- elseif macro_p.x == 7 then
-- upgrade_for_sale = Upgrades.enum.EXTRA_HOLD
-- elseif macro_p.x % 16 < 8 then
-- upgrade_for_sale = Upgrades.enum.MORE_POWER
-- else
-- upgrade_for_sale = Upgrades.enum.EXTRA_HOLD
-- end --upgrades like UNLOCK_MERCHANTS will slot themselves in when necessary, due to .overwrite_a_dock_upgrade() (not anymore)
-- one day it's worth making this system more readable
-- NOTE: When DOCK frequency changes, this needs to change too (kinda bad design, but w/e)
-- NOTE: I couldn't manage to make upgrade overwriting to work so I made it fixed here (although I prefer having fixed for less rng)
-- TODO: Perhaps always have something special to sell (or remove the upgrade market if it has no offers?)
if macro_p.x == 15 then
upgrade_for_sale = Upgrades.enum.ROCKETS_FOR_SALE
elseif macro_p.x == 19 then
upgrade_for_sale = Upgrades.enum.UNLOCK_MERCHANTS
elseif (macro_p.x % 8) == 3 then
upgrade_for_sale = Upgrades.enum.UPGRADE_CANNONS
end
local static_params = Utils.deepcopy(Dock.Data.static_params_default)
static_params.upgrade_for_sale = upgrade_for_sale
static_params.boat_for_sale_type = boat_for_sale_type
@ -598,6 +613,8 @@ function Public.cleanup_old_destination_data() --we do actually access destinati
local memory = Memory.get_crew_memory()
for i, destination_data in pairs(memory.destinations) do
if destination_data.overworld_position.x < memory.overworldx then
Islands[IslandEnum.enum.CAVE].cleanup_cave_surface(memory.destinations[i])
memory.destinations[i] = nil
end
end
@ -620,7 +637,7 @@ function Public.try_overworld_move_v2(vector) --islands stay, crowsnest moves
Public.ensure_lane_generated_up_to(0, memory.overworldx + Crowsnest.Data.visibilitywidth)
Public.ensure_lane_generated_up_to(24, memory.overworldx + Crowsnest.Data.visibilitywidth)
Public.ensure_lane_generated_up_to(-24, memory.overworldx + Crowsnest.Data.visibilitywidth)
Public.overwrite_a_dock_upgrade()
-- Public.overwrite_a_dock_upgrade()
end
if not Public.is_position_free_to_move_to{x = memory.overworldx + vector.x, y = memory.overworldy+ vector.y} then
@ -678,20 +695,21 @@ function Public.try_overworld_move_v2(vector) --islands stay, crowsnest moves
end
-- UNUSED
function Public.overwrite_a_dock_upgrade()
local memory = Memory.get_crew_memory()
if (memory.overworldx % (40*8)) == (40*4-1) then -- pick a point that _must_ be visited, i.e. right before a destination
if (memory.overworldx) == (40*4-1) then -- LEAVE A GAP at x=40*11, because we haven't developed an upgrade to put there yet
for _, dest in pairs(memory.destinations) do
if dest.type == Surfaces.enum.DOCK then
if dest.overworld_position.x == memory.overworldx + 1 + (40*7) then
dest.static_params.upgrade_for_sale = Upgrades.enum.MORE_POWER
end
end
end
else
-- POWER upgrade is disabled at docks
-- if (memory.overworldx) == (40*4-1) then -- LEAVE A GAP at x=40*11, because we haven't developed an upgrade to put there yet
-- for _, dest in pairs(memory.destinations) do
-- if dest.type == Surfaces.enum.DOCK then
-- if dest.overworld_position.x == memory.overworldx + 1 + (40*7) then
-- dest.static_params.upgrade_for_sale = Upgrades.enum.MORE_POWER
-- end
-- end
-- end
-- else
local upgrade_to_overwrite_with
if not memory.dock_overwrite_variable then memory.dock_overwrite_variable = 1 end
@ -724,7 +742,7 @@ function Public.overwrite_a_dock_upgrade()
end
end
end
end
-- end
end
end

View File

@ -134,6 +134,7 @@ function Public.go_from_starting_dock_to_first_destination()
Shop.Captains.initialise_captains_shop()
Hold.create_hold_surface(1)
boat.EEI_stage = 1
Cabin.create_cabin_surface()
local items = Balance.starting_items_crew_upstairs()
@ -169,7 +170,6 @@ function Public.go_from_starting_dock_to_first_destination()
-- go:
-- Public.progress_to_destination(1) --index of first destination
boat.EEI_stage = 1
Boats.update_EEIs(boat)
-- if Common.difficulty_scale() == 1 then

View File

@ -9,6 +9,7 @@ local Math = require 'maps.pirates.math'
local Raffle = require 'maps.pirates.raffle'
-- local Loot = require 'maps.pirates.loot'
local CoreData = require 'maps.pirates.coredata'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local _inspect = require 'utils.inspect'.inspect
@ -21,6 +22,8 @@ local enum = {
RESOURCEFLOW = 'Resource_Flow',
RESOURCECOUNT = 'Resource_Count',
WORMS = 'Worms',
FISH = 'Fish',
COMPILATRON = 'Compilatron', -- compilatron is robot that looks like sheep
}
Public.enum = enum
@ -31,6 +34,8 @@ Public.quest_icons = {
[enum.FIND] = '[img=utility.ghost_time_to_live_modifier_icon]',
[enum.RESOURCEFLOW] = '',
[enum.RESOURCECOUNT] = '',
[enum.FISH] = '[item=raw-fish]',
[enum.COMPILATRON] = '[entity=compilatron]',
}
@ -86,10 +91,14 @@ function Public.initialise_random_quest()
-- Public.initialise_time_quest()
end
function Public.initialise_random_cave_island_quest()
local rng = Math.random(100)
if rng <= 50 then
Public.initialise_fish_quest()
else
Public.initialise_compilatron_quest()
end
end
function Public.initialise_time_quest()
local destination = Common.current_destination()
@ -105,8 +114,7 @@ end
function Public.initialise_find_quest()
local destination = Common.current_destination()
-- @FIXME: Magic numbers
if destination.subtype and destination.subtype == '1' or destination.subtype == '5' or destination.subtype == '6' then
if destination.subtype == IslandEnum.enum.STANDARD or destination.subtype == IslandEnum.enum.RADIOACTIVE or destination.subtype == IslandEnum.enum.STANDARD_VARIANT then
destination.dynamic_data.quest_type = enum.FIND
destination.dynamic_data.quest_reward = Public.quest_reward()
@ -128,7 +136,8 @@ end
function Public.initialise_nodamage_quest()
local destination = Common.current_destination()
if not destination and destination.dynamic_data and destination.dynamic_data.rocketsilomaxhp then return end
-- @FIXME: this if check looks ill-formed when destination is nil
if not destination and destination.dynamic_data and destination.dynamic_data.rocketsilomaxhp then return false end
destination.dynamic_data.quest_type = enum.NODAMAGE
destination.dynamic_data.quest_reward = Public.quest_reward()
@ -139,26 +148,27 @@ function Public.initialise_nodamage_quest()
end
function Public.initialise_resourceflow_quest()
local destination = Common.current_destination()
-- @UNUSED
-- function Public.initialise_resourceflow_quest()
-- local destination = Common.current_destination()
if not destination and destination.dynamic_data and destination.dynamic_data.rocketsilomaxhp then return end
-- if not destination and destination.dynamic_data and destination.dynamic_data.rocketsilomaxhp then return false end
destination.dynamic_data.quest_type = enum.RESOURCEFLOW
destination.dynamic_data.quest_reward = Public.quest_reward()
destination.dynamic_data.quest_progress = 0
-- destination.dynamic_data.quest_type = enum.RESOURCEFLOW
-- destination.dynamic_data.quest_reward = Public.quest_reward()
-- destination.dynamic_data.quest_progress = 0
local generated_flow_quest = Public.generate_flow_quest()
if not generated_flow_quest then return false end
-- local generated_flow_quest = Public.generate_flow_quest()
-- if not generated_flow_quest then return false end
destination.dynamic_data.quest_params = {item = generated_flow_quest.item}
-- destination.dynamic_data.quest_params = {item = generated_flow_quest.item}
local progressneeded_before_rounding = generated_flow_quest.base_rate * Balance.resource_quest_multiplier()
-- local progressneeded_before_rounding = generated_flow_quest.base_rate * Balance.resource_quest_multiplier()
destination.dynamic_data.quest_progressneeded = Math.ceil(progressneeded_before_rounding/10) * 10
-- destination.dynamic_data.quest_progressneeded = Math.ceil(progressneeded_before_rounding/10) * 10
return true
end
-- return true
-- end
function Public.initialise_resourcecount_quest()
@ -192,7 +202,7 @@ end
function Public.initialise_worms_quest()
local destination = Common.current_destination()
if not (destination.surface_name and game.surfaces[destination.surface_name]) then return end
if not (destination.surface_name and game.surfaces[destination.surface_name]) then return false end
local surface = game.surfaces[destination.surface_name]
@ -231,6 +241,33 @@ function Public.initialise_worms_quest()
end
end
-- Catch amount of fish (currently Cave island exclusive, because it's hard to calculate "quest_progressneeded")
function Public.initialise_fish_quest()
local destination = Common.current_destination()
if not destination and destination.dynamic_data then return false end
destination.dynamic_data.quest_type = enum.FISH
destination.dynamic_data.quest_reward = Public.quest_reward()
destination.dynamic_data.quest_progress = 0
destination.dynamic_data.quest_progressneeded = Math.random(300, 450) -- assuming that base caught fish amount is 3
return true
end
-- Rescue compilatrons under the heavy rocks (currently Cave island exclusive, because it's hard to calculate "quest_progressneeded")
function Public.initialise_compilatron_quest()
local destination = Common.current_destination()
if not destination and destination.dynamic_data then return false end
destination.dynamic_data.quest_type = enum.COMPILATRON
destination.dynamic_data.quest_reward = Public.quest_reward()
destination.dynamic_data.quest_progress = 0
destination.dynamic_data.quest_progressneeded = Math.random(30, 40) -- assuming that chance to find compilatron is 1/20
return true
end
function Public.try_resolve_quest()

View File

@ -4,6 +4,7 @@ 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
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
@ -27,6 +28,7 @@ function Public.raffle(values, weights) --arguments of the form {[a] = A, [b] =
end
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
function Public.raffle2(table) --arguments of the form {v1 = w1, v2 = w2, ...}
local total_weight = 0

View File

@ -327,97 +327,96 @@ end
local function class_on_player_used_capsule(event)
local player = game.players[event.player_index]
if not player or not player.valid then
return
end
local player_index = player.index
if not event.player_index then return end
local player = game.players[event.player_index]
if not player then return end
if not player.valid then return end
if not player.character then return end
if not player.character.valid then return end
if not event.item then return end
if event.item.name ~= 'raw-fish' then return end
local class = Public.get_class(player.index)
if not class then return end
local crew_id = Common.get_id_from_force_name(player.force.name)
Memory.set_working_id(crew_id)
local memory = Memory.get_crew_memory()
if not (player.character and player.character.valid) then
return
end
local item = event.item
if not (item and item.name and item.name == 'raw-fish') then return end
local global_memory = Memory.get_global_memory()
global_memory.last_players_health[event.player_index] = player.character.health
if memory.classes_table and memory.classes_table[player_index] then
local class = memory.classes_table[player_index]
if class == Public.enum.GOURMET then
local multiplier = 0
local surfacedata = SurfacesCommon.decode_surface_name(player.surface.name)
if surfacedata.type == SurfacesCommon.enum.CABIN then
multiplier = 0.25
elseif surfacedata.type == SurfacesCommon.enum.CROWSNEST then
multiplier = 0.15
if class == Public.enum.GOURMET then
local multiplier = 0
local surfacedata = SurfacesCommon.decode_surface_name(player.surface.name)
if surfacedata.type == SurfacesCommon.enum.CABIN then
multiplier = 0.25
elseif surfacedata.type == SurfacesCommon.enum.CROWSNEST then
multiplier = 0.15
else
local tile = player.surface.get_tile(player.position)
if tile.valid then
if tile.name == CoreData.world_concrete_tile then
multiplier = 1.5
elseif tile.name == 'cyan-refined-concrete' then
multiplier = 1.6
elseif tile.name == CoreData.walkway_tile then
multiplier = 1
elseif tile.name == 'orange-refined-concrete' then
multiplier = 0.5
elseif tile.name == CoreData.enemy_landing_tile then
multiplier = 0.3
elseif tile.name == CoreData.static_boat_floor then
multiplier = 0.1
end
end
end
if multiplier > 0 then
-- Idea behind this: A diminishing return for ore granted every time fish is eaten. But slowly "reset" the diminishing return overtime
local timescale = 60*30 * Math.max((Balance.game_slowness_scale())^(2/3),0.8)
if memory.gourmet_recency_tick then
multiplier = multiplier * Math.clamp(0.2, 5, (1/5)^((memory.gourmet_recency_tick - game.tick)/(60*300)))
memory.gourmet_recency_tick = Math.max(memory.gourmet_recency_tick, game.tick - timescale*10) + timescale
else
local tile = player.surface.get_tile(player.position)
if tile.valid then
if tile.name == CoreData.world_concrete_tile then
multiplier = 1.5
elseif tile.name == 'cyan-refined-concrete' then
multiplier = 1.6
elseif tile.name == CoreData.walkway_tile then
multiplier = 1
elseif tile.name == 'orange-refined-concrete' then
multiplier = 0.5
elseif tile.name == CoreData.enemy_landing_tile then
multiplier = 0.3
elseif tile.name == CoreData.static_boat_floor then
multiplier = 0.1
end
end
multiplier = multiplier * 5
memory.gourmet_recency_tick = game.tick - timescale*10 + timescale
end
if multiplier > 0 then
local timescale = 60*30 * Math.max((Balance.game_slowness_scale())^(2/3),0.8)
if memory.gourmet_recency_tick then
multiplier = multiplier * Math.clamp(0.2, 5, (1/5)^((memory.gourmet_recency_tick - game.tick)/(60*300)))
memory.gourmet_recency_tick = Math.max(memory.gourmet_recency_tick, game.tick - timescale*10) + timescale
else
multiplier = multiplier * 5
memory.gourmet_recency_tick = game.tick - timescale*10 + timescale
end
Public.class_ore_grant(player, 15 * multiplier, Balance.gourmet_ore_scaling_enabled)
Public.class_ore_grant(player, 15 * multiplier, Balance.gourmet_ore_scaling_enabled)
end
elseif class == Public.enum.ROCK_EATER then
local required_count = Balance.rock_eater_required_stone_furnace_to_heal_count
if player.get_item_count('stone-furnace') >= required_count then
player.remove_item({name='stone-furnace', count=required_count})
player.insert({name='raw-fish', count=1})
end
elseif class == Public.enum.SOLDIER then
local chance = Balance.soldier_defender_summon_chance
if Math.random() < chance then
local random_vec = Math.random_vec(3)
local e = player.surface.create_entity{
name = 'defender',
position = Utils.psum{player.character.position, random_vec},
speed = 1.5,
force = player.force
}
if e and e.valid then
e.combat_robot_owner = player.character
end
elseif class == Public.enum.ROCK_EATER then
local required_count = Balance.rock_eater_required_stone_furnace_to_heal_count
if player.get_item_count('stone-furnace') >= required_count then
player.remove_item({name='stone-furnace', count=required_count})
player.insert({name='raw-fish', count=1})
end
elseif class == Public.enum.SOLDIER then
local chance = Balance.soldier_defender_summon_chance
if Math.random() < chance then
local random_vec = Math.random_vec(3)
local e = player.surface.create_entity{
name = 'defender',
position = Utils.psum{player.character.position, random_vec},
speed = 1.5,
force = player.force
}
if e and e.valid then
e.combat_robot_owner = player.character
end
end
elseif class == Public.enum.VETERAN then
local chance = Balance.veteran_destroyer_summon_chance
if Math.random() < chance then
local random_vec = Math.random_vec(3)
local e = player.surface.create_entity{
name = 'destroyer',
position = Utils.psum{player.character.position, random_vec},
speed = 1.5,
force = player.force
}
if e and e.valid then
e.combat_robot_owner = player.character
end
end
elseif class == Public.enum.VETERAN then
local chance = Balance.veteran_destroyer_summon_chance
if Math.random() < chance then
local random_vec = Math.random_vec(3)
local e = player.surface.create_entity{
name = 'destroyer',
position = Utils.psum{player.character.position, random_vec},
speed = 1.5,
force = player.force
}
if e and e.valid then
e.combat_robot_owner = player.character
end
end
end
@ -432,10 +431,12 @@ function Public.lumberjack_bonus_items(give_table)
give_table[#give_table + 1] = {name = 'coin', count = a}
memory.playtesting_stats.coins_gained_by_trees_and_rocks = memory.playtesting_stats.coins_gained_by_trees_and_rocks + a
elseif Math.random(2) == 1 then
if Math.random(5) == 1 then
give_table[#give_table + 1] = {name = 'copper-ore', count = 1}
local multiplier = Balance.island_richness_avg_multiplier() * Math.random_float_in_range(1, 1.5)
local amount = Math.ceil(Balance.lumberjack_ore_base_amount * multiplier)
if Math.random(4) == 1 then
give_table[#give_table + 1] = {name = 'copper-ore', count = amount}
else
give_table[#give_table + 1] = {name = 'iron-ore', count = 1}
give_table[#give_table + 1] = {name = 'iron-ore', count = amount}
end
end
end
@ -453,6 +454,8 @@ function Public.try_unlock_class(class_for_sale, player, force_unlock)
return false
end
if not Public.class_is_obtainable(class_for_sale) then return false end
if required_class then
-- check if pre-requisite class is taken by someone
for p_index, chosen_class in pairs(memory.classes_table) do
@ -500,6 +503,8 @@ function Public.try_unlock_class(class_for_sale, player, force_unlock)
-- update GUI data
memory.unlocked_classes[#memory.unlocked_classes + 1] = {class = class_for_sale}
end
return true
end
else -- there is no required class
-- if player who unlocked class doesn't have one equipped, equip it for him

View File

@ -58,7 +58,7 @@ function Public.unmake_officer(captain, player)
local force = memory.force
if Utils.contains(Common.crew_get_crew_members(), player) then
if memory.officers_table[player.index] then
if Common.is_officer(player.index) then
memory.officers_table[player.index] = nil
Common.notify_force_light(force,{'pirates.roles_unmake_officer', captain.name, player.name})
@ -96,13 +96,13 @@ function Public.tag_text(player)
tags[#tags + 1] = 'Cap\'n'
elseif player.controller_type == defines.controllers.spectator then
tags[#tags + 1] = 'Spectating'
elseif memory.officers_table and memory.officers_table[player.index] then
elseif Common.is_officer(player.index) then
tags[#tags + 1] = 'Officer'
end
local classes_table = memory.classes_table
if classes_table and classes_table[player.index] then
tags[#tags + 1] = Classes.eng_form[classes_table[player.index]]
local class = Classes.get_class(player.index)
if class then
tags[#tags + 1] = Classes.eng_form[class]
end
for i, t in ipairs(tags) do
@ -161,7 +161,7 @@ function Public.player_privilege_level(player)
if Common.is_id_valid(memory.id) and Common.is_captain(player) then
return Public.privilege_levels.CAPTAIN
elseif memory.officers_table and memory.officers_table[player.index] then
elseif Common.is_officer(player.index) then
return Public.privilege_levels.OFFICER
else
return Public.privilege_levels.NORMAL
@ -217,15 +217,17 @@ function Public.player_left_so_redestribute_roles(player)
end
-- no need to do this, as long as officers get reset when the captainhood changes hands
-- if memory.officers_table and memory.officers_table[player.index] then
-- if Common.is_officer(player.index) then
-- memory.officers_table[player.index] = nil
-- end
local memory = Memory.get_crew_memory()
local class = Classes.get_class(player.index)
-- free up the class
if memory.classes_table and memory.classes_table[player.index] then
memory.spare_classes[#memory.spare_classes + 1] = memory.classes_table[player.index]
if class then
memory.spare_classes[#memory.spare_classes + 1] = class
memory.classes_table[player.index] = nil
for _, class_entry in ipairs(memory.unlocked_classes) do
@ -263,7 +265,7 @@ function Public.resign_as_officer(player)
local memory = Memory.get_crew_memory()
local force = memory.force
if memory.officers_table and memory.officers_table[player.index] then
if Common.is_officer(player.index) then
memory.officers_table[player.index] = nil
@ -441,7 +443,7 @@ function Public.captain_tax(captain_index)
for _, player_index in pairs(crew_members) do
if player_index ~= captain_index then
local player = game.players[player_index]
if player and player.valid and not (memory.officers_table and memory.officers_table[player.index]) then
if player and player.valid and not (Common.is_officer(player.index)) then
local inv = player.get_inventory(defines.inventory.character_main)
if inv and inv.valid then
for _, i in pairs(items_to_req) do

View File

@ -26,8 +26,7 @@ function Public.class_update_auxiliary_data(tickinterval)
for _, player in pairs(crew) do
local player_index = player.index
local class = memory.classes_table[player_index]
if class and class == Classes.enum.IRON_LEG then
if Classes.get_class(player_index) == Classes.enum.IRON_LEG then
if (not class_auxiliary_data[player_index]) then class_auxiliary_data[player_index] = {} end
local data = class_auxiliary_data[player_index]
processed_players[player_index] = true
@ -68,7 +67,7 @@ function Public.class_renderings(tickinterval)
for _, player in pairs(crew) do
local player_index = player.index
local class = memory.classes_table[player_index]
local class = Classes.get_class(player_index)
if class then
if not class_renderings[player_index] then class_renderings[player_index] = {} end
local rendering_data = class_renderings[player_index]
@ -166,7 +165,14 @@ function Public.update_character_properties(tickinterval)
if Common.validate_player_and_character(player) then
local player_index = player.index
local character = player.character
local class = memory.classes_table and memory.classes_table[player_index] or nil
local class = Classes.get_class(player_index)
local speed_boost = Balance.base_extra_character_speed
if memory.speed_boost_characters and memory.speed_boost_characters[player_index] then
speed_boost = speed_boost * Balance.respawn_speed_boost
end
if class then
--local max_reach_bonus = 0
-- if memory.classes_table[player_index] == Classes.enum.DECKHAND then
@ -186,43 +192,6 @@ function Public.update_character_properties(tickinterval)
character.character_reach_distance_bonus = 0
end
--character.character_reach_distance_bonus = max_reach_bonus
end
local health_boost = 0 -- base health is 250
-- moved to damage resistance:
-- if memory.classes_table and memory.classes_table[player_index] then
-- local class = memory.classes_table[player_index]
-- if class == Classes.enum.SAMURAI then
-- health_boost = health_boost + 800
-- elseif class == Classes.enum.HATAMOTO then
-- health_boost = health_boost + 1300
-- end
-- end
-- Captain health boost:
-- if Common.is_captain(player) then
-- health_boost = health_boost + 50
-- end
character.character_health_bonus = health_boost
-- == DO NOT DO THIS!: Removing inventory slots is evil. The player can spill inventory
-- if Common.is_captain(player) then
-- if player.character and player.character.valid then
-- player.character_inventory_slots_bonus = 20
-- end
-- else
-- if player.character and player.character.valid then
-- player.character_inventory_slots_bonus = 0
-- end
-- end
local speed_boost = Balance.base_extra_character_speed
if memory.speed_boost_characters and memory.speed_boost_characters[player_index] then
speed_boost = speed_boost * Balance.respawn_speed_boost
elseif memory.classes_table and memory.classes_table[player_index] then
if class == Classes.enum.SCOUT then
speed_boost = speed_boost * Balance.scout_extra_speed
elseif (class == Classes.enum.DECKHAND) or (class == Classes.enum.BOATSWAIN) or (class == Classes.enum.SHORESMAN) then
@ -246,7 +215,38 @@ function Public.update_character_properties(tickinterval)
end
end
end
character.character_running_speed_modifier = speed_boost - 1
local health_boost = 0 -- base health is 250
character.character_health_bonus = health_boost
-- moved to damage resistance:
-- if memory.classes_table and memory.classes_table[player_index] then
-- local class = memory.classes_table[player_index]
-- if class == Classes.enum.SAMURAI then
-- health_boost = health_boost + 800
-- elseif class == Classes.enum.HATAMOTO then
-- health_boost = health_boost + 1300
-- end
-- end
-- Captain health boost:
-- if Common.is_captain(player) then
-- health_boost = health_boost + 50
-- end
-- == DO NOT DO THIS!: Removing inventory slots is evil. The player can spill inventory
-- if Common.is_captain(player) then
-- if player.character and player.character.valid then
-- player.character_inventory_slots_bonus = 20
-- end
-- else
-- if player.character and player.character.valid then
-- player.character_inventory_slots_bonus = 0
-- end
-- end
end
end
end
@ -257,40 +257,37 @@ function Public.class_rewards_tick(tickinterval)
local crew = Common.crew_get_crew_members()
for _, player in pairs(crew) do
local class = Classes.get_class(player.index)
if Common.validate_player_and_character(player) and
game.tick % tickinterval == 0 and
memory.classes_table and
memory.classes_table[player.index]
then
local class = memory.classes_table[player.index]
class and
not Boats.is_boat_at_sea() and --it is possible to spend infinite time here, so don't give out freebies
(
class == Classes.enum.DECKHAND or
class == Classes.enum.SHORESMAN or
class == Classes.enum.BOATSWAIN or
class == Classes.enum.QUARTERMASTER
)
then --watch out for this line! (why?)
local surfacedata = Surfaces.SurfacesCommon.decode_surface_name(player.surface.name)
local type = surfacedata.type
local on_ship_bool = (type == Surfaces.enum.HOLD) or (type == Surfaces.enum.CABIN) or (type == Surfaces.enum.CROWSNEST) or (player.surface.name == memory.boat.surface_name and Boats.on_boat(memory.boat, player.position))
local hold_bool = (type == Surfaces.enum.HOLD)
if not Boats.is_boat_at_sea() and --it is possible to spend infinite time here, so don't give out freebies
(
class == Classes.enum.DECKHAND or
class == Classes.enum.SHORESMAN or
class == Classes.enum.BOATSWAIN or
class == Classes.enum.QUARTERMASTER
)
then --watch out for this line! (why?)
local surfacedata = Surfaces.SurfacesCommon.decode_surface_name(player.surface.name)
local type = surfacedata.type
local on_ship_bool = (type == Surfaces.enum.HOLD) or (type == Surfaces.enum.CABIN) or (type == Surfaces.enum.CROWSNEST) or (player.surface.name == memory.boat.surface_name and Boats.on_boat(memory.boat, player.position))
local hold_bool = (type == Surfaces.enum.HOLD)
if class == Classes.enum.DECKHAND and on_ship_bool and (not hold_bool) then
Classes.class_ore_grant(player, Balance.deckhand_ore_grant_multiplier, Balance.deckhand_ore_scaling_enabled)
elseif class == Classes.enum.BOATSWAIN and hold_bool then
Classes.class_ore_grant(player, Balance.boatswain_ore_grant_multiplier, Balance.boatswain_ore_scaling_enabled)
elseif class == Classes.enum.SHORESMAN and (not on_ship_bool) then
Classes.class_ore_grant(player, Balance.shoresman_ore_grant_multiplier, Balance.shoresman_ore_scaling_enabled)
elseif class == Classes.enum.QUARTERMASTER then
local nearby_players = #player.surface.find_entities_filtered{position = player.position, radius = Balance.quartermaster_range, name = 'character'}
if class == Classes.enum.DECKHAND and on_ship_bool and (not hold_bool) then
Classes.class_ore_grant(player, Balance.deckhand_ore_grant_multiplier, Balance.deckhand_ore_scaling_enabled)
elseif class == Classes.enum.BOATSWAIN and hold_bool then
Classes.class_ore_grant(player, Balance.boatswain_ore_grant_multiplier, Balance.boatswain_ore_scaling_enabled)
elseif class == Classes.enum.SHORESMAN and (not on_ship_bool) then
Classes.class_ore_grant(player, Balance.shoresman_ore_grant_multiplier, Balance.shoresman_ore_scaling_enabled)
elseif class == Classes.enum.QUARTERMASTER then
local nearby_players = #player.surface.find_entities_filtered{position = player.position, radius = Balance.quartermaster_range, name = 'character'}
if nearby_players > 1 then
Classes.class_ore_grant(player, nearby_players - 1, Balance.quartermaster_ore_scaling_enabled)
end
if nearby_players > 1 then
Classes.class_ore_grant(player, nearby_players - 1, Balance.quartermaster_ore_scaling_enabled)
end
end
end
-- Smoldering class is disabled
-- if memory.classes_table and memory.classes_table[player.index] then
@ -312,7 +309,6 @@ function Public.class_rewards_tick(tickinterval)
-- end
-- end
-- end
end
end
end

View File

@ -28,11 +28,11 @@ local Public = {}
-- WARNING: The Crowsnest caption pulls data from this data. But the actual dock market pulls from boat_upgrades.lua.
Public.main_shop_data_1 = {
upgrade_cannons = {
tooltip = 'Increase cannons max health. This will also repair them.',
what_you_get_sprite_buttons = {['item/artillery-turret'] = false},
base_cost = {coins = 1000},
},
-- upgrade_cannons = {
-- tooltip = 'Increase cannons max health. This will also repair them.',
-- what_you_get_sprite_buttons = {['item/artillery-turret'] = false},
-- base_cost = {coins = 1000},
-- },
new_boat_cutter = {
tooltip = 'Purchase a cutter.',
what_you_get_sprite_buttons = {['utility/spawn_flag'] = false},
@ -70,25 +70,30 @@ Public.main_shop_data_1 = {
-- },
-- as as initial pass let's try making the fuel values half of the old gold values...
[Upgrades.enum.MORE_POWER] = {
tooltip = 'Upgrade the ship\'s power.',
tooltip = {'pirates.market_description_upgrade_power'},
what_you_get_sprite_buttons = {['utility/status_working'] = false},
base_cost = {coins = 7000, fuel = 500},
},
[Upgrades.enum.EXTRA_HOLD] = {
tooltip = 'Upgrade the ship\'s hold.',
tooltip = {'pirates.market_description_upgrade_hold'},
what_you_get_sprite_buttons = {['item/steel-chest'] = false},
base_cost = {coins = 7000, fuel = 500},
},
[Upgrades.enum.UNLOCK_MERCHANTS] = {
tooltip = 'Unlock merchant ships.',
tooltip = {'pirates.market_description_upgrade_merchants'},
what_you_get_sprite_buttons = {['entity/market'] = false},
base_cost = {coins = 14000, fuel = 1000},
},
[Upgrades.enum.ROCKETS_FOR_SALE] = {
tooltip = 'Unlock rockets for sale at covered-up markets.',
tooltip = {'pirates.market_description_upgrade_rockets'},
what_you_get_sprite_buttons = {['item/rocket-launcher'] = false},
base_cost = {coins = 21000, fuel = 1000},
},
[Upgrades.enum.UPGRADE_CANNONS] = {
tooltip = {'pirates.market_description_upgrade_turrets'},
what_you_get_sprite_buttons = {['item/artillery-turret'] = false},
base_cost = {coins = 5000, fuel = 800},
},
}
Public.main_shop_data_2 = {

View File

@ -17,6 +17,7 @@ local _inspect = require 'utils.inspect'.inspect
local Public = {}
-- What is this even for?
local enum = {
TIME = 'Time',
}
@ -55,6 +56,11 @@ Public.offers_default = {
{price = {{'coin', 1700}}, offer = {type = 'give-item', item = 'flamethrower-ammo', count = 15}},
{price = {{'coin', 1800}}, offer = {type = 'give-item', item = 'flamethrower-ammo', count = 20}},
{price = {{'coin', 1800}}, offer = {type = 'give-item', item = 'flying-robot-frame', count = 5}},
{price = {{'coin', 1000}}, offer = {type = 'give-item', item = 'logistic-chest-storage', count = 5}},
{price = {{'coin', 1000}}, offer = {type = 'give-item', item = 'logistic-chest-passive-provider', count = 5}},
{price = {{'coin', 2500}}, offer = {type = 'give-item', item = 'logistic-chest-active-provider', count = 5}},
{price = {{'coin', 2500}}, offer = {type = 'give-item', item = 'logistic-chest-buffer', count = 5}},
{price = {{'coin', 2500}}, offer = {type = 'give-item', item = 'logistic-chest-requester', count = 5}},
}

View File

@ -158,8 +158,6 @@ function Public.create_dock_markets(surface, p)
-- e.add_market_item{price = {{'repair-pack', 20}, {'coin', 1000}}, offer = {type = 'give-item', item = 'artillery-turret', count = 1}}
-- end
e.add_market_item{price = {{'repair-pack', 20}, {'coin', 1000}}, offer = {type = 'give-item', item = 'artillery-turret', count = 1}}
local upgrade_for_sale = Common.current_destination().static_params.upgrade_for_sale
if upgrade_for_sale then
e.add_market_item(Upgrades.market_offer_form[upgrade_for_sale])

View File

@ -21,14 +21,14 @@ function Public.generate_merchant_trades(market)
if market and market.valid then
local game_completion_progress = Common.game_completion_progress()
if game_completion_progress < 0.96 then
market.add_market_item{price = {{'coin', 8000}, {'raw-fish', 100}}, offer = {type = 'give-item', item = 'modular-armor', count = 1}}
market.add_market_item{price = {{'coin', 5000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'battery-equipment', count = 1}}
market.add_market_item{price = {{'coin', 2000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'solar-panel-equipment', count = 5}}
market.add_market_item{price = {{'coin', 1000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'night-vision-equipment', count = 1}}
market.add_market_item{price = {{'coin', 2000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'energy-shield-equipment', count = 1}}
market.add_market_item{price = {{'coin', 1000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'personal-roboport-equipment', count = 1}}
else
market.add_market_item{price = {{'coin', 8000}, {'raw-fish', 100}}, offer = {type = 'give-item', item = 'modular-armor', count = 1}}
market.add_market_item{price = {{'coin', 5000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'battery-equipment', count = 1}}
market.add_market_item{price = {{'coin', 2000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'solar-panel-equipment', count = 5}}
market.add_market_item{price = {{'coin', 1000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'night-vision-equipment', count = 1}}
market.add_market_item{price = {{'coin', 2000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'energy-shield-equipment', count = 1}}
market.add_market_item{price = {{'coin', 1000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'personal-roboport-equipment', count = 1}}
if game_completion_progress >= 0.96 then
market.add_market_item{price = {{'coin', 8000}, {'raw-fish', 100}}, offer = {type = 'give-item', item = 'modular-armor', count = 1}}
market.add_market_item{price = {{'coin', 12000}, {'raw-fish', 100}}, offer = {type = 'give-item', item = 'power-armor', count = 1}}
market.add_market_item{price = {{'coin', 5000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'battery-equipment', count = 1}}
@ -42,19 +42,10 @@ function Public.generate_merchant_trades(market)
market.add_market_item{price = {{'coin', 4000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'personal-roboport-mk2-equipment', count = 1}}
market.add_market_item{price = {{'coin', 8000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'exoskeleton-equipment', count = 1}}
market.add_market_item{price = {{'coin', 10000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'personal-laser-defense-equipment', count = 1}}
-- else
-- market.add_market_item{price = {{'coin', 18000}, {'raw-fish', 100}}, offer = {type = 'give-item', item = 'power-armor', count = 1}}
-- market.add_market_item{price = {{'coin', 24000}, {'raw-fish', 100}}, offer = {type = 'give-item', item = 'power-armor-mk2', count = 1}}
-- market.add_market_item{price = {{'coin', 10000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'battery-mk2-equipment', count = 1}}
-- market.add_market_item{price = {{'coin', 400}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'solar-panel-equipment', count = 1}}
-- market.add_market_item{price = {{'coin', 6000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'fusion-reactor-equipment', count = 1}}
-- market.add_market_item{price = {{'coin', 1000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'night-vision-equipment', count = 1}}
-- market.add_market_item{price = {{'coin', 5000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'energy-shield-mk2-equipment', count = 1}}
-- market.add_market_item{price = {{'coin', 4000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'personal-roboport-mk2-equipment', count = 1}}
-- market.add_market_item{price = {{'coin', 8000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'exoskeleton-equipment', count = 1}}
-- market.add_market_item{price = {{'coin', 10000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'personal-laser-defense-equipment', count = 1}}
end
if game_completion_progress >= 2 then
market.add_market_item{price = {{'coin', 30000}, {'raw-fish', 100}}, offer = {type = 'give-item', item = 'power-armor-mk2', count = 1}}
end
end
end

View File

@ -4,7 +4,7 @@
local Memory = require 'maps.pirates.memory'
-- local Roles = require 'maps.pirates.roles.roles'
local Classes = require 'maps.pirates.roles.classes'
local Crew = require 'maps.pirates.crew'
-- local Crew = require 'maps.pirates.crew'
-- local Boats = require 'maps.pirates.structures.boats.boats'
-- local Dock = require 'maps.pirates.surfaces.dock'
local Balance = require 'maps.pirates.balance'
@ -15,6 +15,7 @@ local Math = require 'maps.pirates.math'
local _inspect = require 'utils.inspect'.inspect
local SurfacesCommon = require 'maps.pirates.surfaces.common'
local Upgrades = require 'maps.pirates.boat_upgrades'
local Cabin = require 'maps.pirates.surfaces.cabin'
-- local Upgrades = require 'maps.pirates.boat_upgrades'
local Public = {}
@ -197,11 +198,6 @@ function Public.event_on_market_item_purchased(event)
local force = player.force
if thisPurchaseData.dock_upgrades_market then
if thisPurchaseData.offer_type == 'give-item' then
-- this is the dummy artillery purchase
inv.remove{name = thisPurchaseData.offer_giveitem_name, count = thisPurchaseData.offer_giveitem_count}
end
if thisPurchaseData.permission_level_fail then
refunds = trade_count
Common.notify_player_error(player, {'pirates.market_error_not_captain'})
@ -209,30 +205,13 @@ function Public.event_on_market_item_purchased(event)
Public.refund_items(player, thisPurchaseData.price, 1)
refunds = refunds + 1
else
if thisPurchaseData.offer_type == 'give-item' then
-- heal all cannons:
local cannons = game.surfaces[destination.surface_name].find_entities_filtered({type = 'artillery-turret'})
for _, c in pairs(cannons) do
local unit_number = c.unit_number
local healthbar = memory.boat.healthbars[unit_number]
if healthbar then
healthbar.max_health = healthbar.max_health + Balance.cannon_extra_hp_for_upgrade
healthbar.health = healthbar.max_health
Common.update_healthbar_rendering(healthbar, healthbar.max_health)
else
log('error: healthbar ' .. unit_number .. ' not found')
end
end
Common.notify_force(force,{'pirates.upgraded_cannons', player.name})
market.remove_market_item(offer_index)
local upgrade_type = Common.current_destination().static_params.upgrade_for_sale
if upgrade_type then
Upgrades.execute_upgade(upgrade_type, player)
else
local upgrade_type = Common.current_destination().static_params.upgrade_for_sale
if upgrade_type then
Upgrades.execute_upgade(upgrade_type, player)
end
market.remove_market_item(offer_index)
log('Error purchasing upgrade at dock')
end
market.remove_market_item(offer_index)
end
else
@ -302,25 +281,36 @@ function Public.event_on_market_item_purchased(event)
end
else
-- print:
if (thisPurchaseData.price and thisPurchaseData.price[1]) then
if not (thisPurchaseData.price[1].name and thisPurchaseData.price[1].name == 'burner-mining-drill') then --this one is too boring to announce
if thisPurchaseData.in_captains_cabin and thisPurchaseData.offer_type == 'nothing' then
Common.notify_force_light(player.force, {'pirates.market_event_buy', player.name, {'pirates.extra_time_at_sea'}, thisPurchaseData.price[1].amount .. ' ' .. thisPurchaseData.price[1].name})
else
Public.print_transaction(player, trade_count - refunds, thisPurchaseData.offer_giveitem_name, thisPurchaseData.offer_giveitem_count, thisPurchaseData.price)
end
end
end
-- if (thisPurchaseData.price and thisPurchaseData.price[1]) then
-- if not (thisPurchaseData.price[1].name and thisPurchaseData.price[1].name == 'burner-mining-drill') then --this one is too boring to announce
-- if thisPurchaseData.in_captains_cabin and thisPurchaseData.offer_type == 'nothing' then
-- Common.notify_force_light(player.force, {'pirates.market_event_buy', player.name, {'pirates.extra_time_at_sea'}, thisPurchaseData.price[1].amount .. ' ' .. thisPurchaseData.price[1].name})
-- else
-- Public.print_transaction(player, trade_count - refunds, thisPurchaseData.offer_giveitem_name, thisPurchaseData.offer_giveitem_count, thisPurchaseData.price)
-- end
-- end
-- end
if thisPurchaseData.in_captains_cabin and thisPurchaseData.offer_type == 'nothing' then
local success = Crew.try_add_extra_time_at_sea(60 * 60)
if not success then
Common.notify_player_error(player, {'pirates.market_error_maximum_loading_time'})
-- refund:
Public.refund_items(player, thisPurchaseData.price, 1)
refunds = refunds + 1
if offer_index == Cabin.enum.SLOT_EXTRA_HOLD then
Upgrades.execute_upgade(Upgrades.enum.EXTRA_HOLD, player)
elseif offer_index == Cabin.enum.SLOT_MORE_POWER then
Upgrades.execute_upgade(Upgrades.enum.MORE_POWER, player)
end
Cabin.handle_purchase(market, offer_index)
-- local success = Crew.try_add_extra_time_at_sea(60 * 60)
-- if not success then
-- Common.notify_player_error(player, {'pirates.market_error_maximum_loading_time'})
-- -- refund:
-- Public.refund_items(player, thisPurchaseData.price, 1)
-- refunds = refunds + 1
-- end
else
if thisPurchaseData.price and thisPurchaseData.price[1] then
Public.print_transaction(player, trade_count - refunds, thisPurchaseData.offer_giveitem_name, thisPurchaseData.offer_giveitem_count, thisPurchaseData.price)
end
if thisPurchaseData.decay_type == 'static' then
if not inv then return end

View File

@ -1,6 +1,7 @@
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
-- local SurfacesCommon = require 'maps.pirates.surfaces.common'
local Memory = require 'maps.pirates.memory'
local Math = require 'maps.pirates.math'
local Balance = require 'maps.pirates.balance'
@ -10,7 +11,8 @@ local Hold = require 'maps.pirates.surfaces.hold'
-- local Parrot = require 'maps.pirates.parrot'
local Cabin = require 'maps.pirates.surfaces.cabin'
local Utils = require 'maps.pirates.utils_local'
local _inspect = require 'utils.inspect'.inspect
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
-- local _inspect = require 'utils.inspect'.inspect
-- DEV NOTE: If making boat designs that have rails, make sure the boat is placed at odd co-ordinates before blueprinting.
@ -63,12 +65,17 @@ function Public.currentdestination_move_boat_natural()
if (destination and destination.dynamic_data and destination.dynamic_data.timer) and (not (destination.dynamic_data.timer >= 1)) then return end
local water_type = 'water'
if destination and destination.subtype == IslandEnum.enum.RADIOACTIVE then
water_type = 'water-green'
end
if boat and boat.state == enum_state.LEAVING_DOCK or boat.state == enum_state.APPROACHING then
local newp = {x = boat.position.x + Common.boat_steps_at_a_time, y = boat.position.y}
Public.teleport_boat(boat, nil, newp)
Public.teleport_boat(boat, nil, newp, nil, water_type)
elseif boat and boat.state == enum_state.RETREATING then
local newp = {x = boat.position.x - Common.boat_steps_at_a_time, y = boat.position.y}
Public.teleport_boat(boat, nil, newp)
Public.teleport_boat(boat, nil, newp, nil, water_type)
end
end
@ -156,7 +163,7 @@ end
function Public.update_EEIs(boat)
local EEI_stage = boat.EEI_stage or 1
local EEI_stage = boat.EEI_stage
local multiplier
if EEI_stage > #Balance.EEI_stages then --sensible out of bounds behaviour:
@ -184,6 +191,27 @@ function Public.update_EEIs(boat)
end
function Public.upgrade_cannons()
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
local cannons = game.surfaces[destination.surface_name].find_entities_filtered({type = 'artillery-turret'})
for _, c in pairs(cannons) do
local unit_number = c.unit_number
local healthbar = memory.boat.healthbars[unit_number]
if healthbar then
healthbar.max_health = healthbar.max_health + Balance.cannon_extra_hp_for_upgrade
healthbar.health = healthbar.max_health
Common.update_healthbar_rendering(healthbar, healthbar.max_health)
else
-- TODO: Upgrade works fine, just seems that redundant artilleries are added to healthbar list which get invalid after surface teleportation (?). Not critical, but would be cool if this was fixed some time.
log('Error (non-critical): artillery\'s healthbar ' .. unit_number .. ' not found')
end
end
end
function Public.upgrade_chests(boat, new_chest)
local scope = Public.get_scope(boat)
local surface = game.surfaces[boat.surface_name]
@ -840,7 +868,7 @@ local function process_entity_on_boat_teleportable(memory, boat, newsurface, new
local p = Utils.deepcopy(e.position)
local p2 = {x = p.x + vector.x, y = p.y + vector.y}
if e.type and e.type == 'electric-pole' then
if e.type == 'electric-pole' then
for k, v in pairs(e.neighbours or {}) do
if k == 'copper' then --red and green cases handled by circuit_neighbours_matrix
if not electric_pole_neighbours_matrix[k] then electric_pole_neighbours_matrix[k] = {} end
@ -877,17 +905,25 @@ local function process_entity_on_boat_teleportable(memory, boat, newsurface, new
end
end
local ee = e.clone{position = p2, surface = newsurface, create_build_effect_smoke = false}
-- Special case for vehicles, because currently they can be exclusively teleported between surfaces
local ee
if e.name == 'car' or e.name == 'tank' or e.name == 'spidertron' then
e.teleport(p2, newsurface)
else
ee = e.clone{position = p2, surface = newsurface, create_build_effect_smoke = false}
end
if boat.upstairs_pole and e == boat.upstairs_pole then
boat.upstairs_pole = ee
Public.try_connect_upstairs_and_downstairs_poles(boat)
end
e.destroy()
if not (e.name == 'car' or e.name == 'tank' or e.name == 'spidertron') then
e.destroy()
end
-- Right now in the game we don't expect any non-player characters, so let's kill them to make a point:
if ee and ee.valid and ee.name and ee.name == 'character' and (not ee.player) then
if ee and ee.valid and ee.name == 'character' and (not ee.player) then
ee.die()
end
@ -979,7 +1015,8 @@ local function process_entity_on_boat(memory, boat, newsurface, newposition, vec
unique_entities_list[#unique_entities_list + 1] = e
local name = e.name
if name and name == 'item-on-ground' then
-- NOTE: This sometimes causes items on belts to be sent to cabin, which maybe could be fixed?
if name == 'item-on-ground' then
Common.give_items_to_crew{{name = e.stack.name, count = e.stack.count}}
e.destroy()
else
@ -1027,7 +1064,14 @@ local function teleport_handle_wake_tiles(boat, dummyboat, newsurface_name, olds
for _, area in pairs(wakeareas) do
for _, p in pairs(Common.central_positions_within_area(area, adjustednewposition)) do
local t = old_water_tile
if static_params and static_params.deepwater_xposition and (p.x <= static_params.deepwater_xposition - 0.5) then t = 'deepwater' end
if static_params and static_params.deepwater_xposition and (p.x <= static_params.deepwater_xposition - 0.5) then
if t == 'water' then
t = 'deepwater'
else
t = 'deepwater-green'
end
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
end

View File

@ -277,6 +277,10 @@ function Public.entry_price()
local item = Raffle.LambdaRaffle(Public.entry_price_data_raw, lambda)
if not item then
item = Common.get_random_dictionary_entry(Public.entry_price_data_raw, true)
end
local batchSize = Public.entry_price_data_raw[item].itemBatchSize
return {

View File

@ -276,6 +276,10 @@ function Public.entry_price()
local item = Raffle.LambdaRaffle(Public.entry_price_data_raw, lambda)
if not item then
item = Common.get_random_dictionary_entry(Public.entry_price_data_raw, true)
end
local raw_materials = Public.entry_price_data_raw[item].raw_materials
return {

View File

@ -9,7 +9,7 @@ local CoreData = require 'maps.pirates.coredata'
local Utils = require 'maps.pirates.utils_local'
local _inspect = require 'utils.inspect'.inspect
-- local CustomEvents = require 'maps.pirates.custom_events'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
-- local Raffle = require 'maps.pirates.raffle'
-- local ShopCovered = require 'maps.pirates.shop.covered'
-- local Classes = require 'maps.pirates.roles.classes'
@ -33,7 +33,7 @@ function Public.choose_quest_structure_type()
local rng = Math.random(3)
if rng == 1 or subtype and subtype == IslandsCommon.enum.WALKWAYS then
if rng == 1 or subtype and subtype == IslandEnum.enum.WALKWAYS then
return enum.MARKET1
else

View File

@ -90,6 +90,7 @@ function Public.configure_structure_entities(special_name, components)
local l = loot[i]
inv.insert(l)
end
elseif e.name == 'stone-furnace' then
local inv = e.get_inventory(defines.inventory.fuel)
local loot = Loot.stone_furnace_loot()
@ -97,6 +98,7 @@ function Public.configure_structure_entities(special_name, components)
local l = loot[i]
inv.insert(l)
end
elseif e.name == 'roboport' then
local inv = e.get_inventory(defines.inventory.roboport_robot)
local loot = Loot.roboport_bots_loot()
@ -104,44 +106,55 @@ function Public.configure_structure_entities(special_name, components)
local l = loot[i]
inv.insert(l)
end
elseif e.name == 'centrifuge' then
local inv = e.get_inventory(defines.inventory.assembling_machine_input)
e.set_recipe('kovarex-enrichment-process')
inv.insert{name = 'uranium-235', count = 20}
elseif e.name == 'gun-turret' and special_name == 'small_radioactive_centrifuge' then
e.force = memory.force
elseif e.name == 'fast-splitter' and special_name == 'small_radioactive_centrifuge' then
e.splitter_output_priority = 'left'
e.splitter_filter = 'uranium-235'
elseif e.name == 'storage-tank' and special_name == 'swamp_lonely_storage_tank' then
e.insert_fluid(Loot.swamp_storage_tank_fluid_loot())
elseif e.name == 'storage-tank' and special_name == 'small_oilrig_base' then
e.insert_fluid(Loot.storage_tank_fluid_loot('crude-oil'))
elseif e.name == 'storage-tank' and special_name == 'small_abandoned_refinery' then
e.insert_fluid(Loot.storage_tank_fluid_loot('petroleum-gas'))
elseif e.name == 'storage-tank' and (not (special_name == 'small_radioactive_reactor')) then
e.insert_fluid(Loot.storage_tank_fluid_loot())
elseif (special_name == 'maze_labs') and e.name == 'lab' then
elseif e.name == 'lab' and (special_name == 'maze_labs' or special_name == 'small_radioactive_lab') then
local inv = e.get_inventory(defines.inventory.lab_input)
local loot = Loot.maze_lab_loot()
local loot = Loot.lab_loot()
for i = 1, #loot do
local l = loot[i]
inv.insert(l)
end
elseif (special_name == 'maze_treasure') and e.name == 'steel-chest' then
elseif e.name == 'steel-chest' and special_name == 'maze_treasure' then
local inv = e.get_inventory(defines.inventory.chest)
local loot = Loot.maze_treasure_loot()
for i = 1, #loot do
local l = loot[i]
inv.insert(l)
end
elseif (special_name == 'maze_defended_camp' or special_name == 'maze_undefended_camp') and e.name == 'wooden-chest' then
elseif e.name == 'wooden-chest' and (special_name == 'maze_defended_camp' or special_name == 'maze_undefended_camp') then
local inv = e.get_inventory(defines.inventory.chest)
local loot = Loot.maze_camp_loot()
for i = 1, #loot do
local l = loot[i]
inv.insert(l)
end
elseif special_name == 'small_cliff_base' then
-- this is to make friendly gun turrets work
e.force = memory.force
@ -165,7 +178,7 @@ function Public.configure_structure_entities(special_name, components)
end
end
if force_name and string.sub(force_name, 1, 15) and string.sub(force_name, 1, 15) == 'ancient-hostile' then
if force_name and string.sub(force_name, 1, 15) == 'ancient-hostile' then
if e.name == 'gun-turret' then
if memory.overworldx < 800 then
e.insert({name = "piercing-rounds-magazine", count = 64})
@ -173,7 +186,8 @@ function Public.configure_structure_entities(special_name, components)
e.insert({name = "uranium-rounds-magazine", count = 64})
end
end
elseif force_name and string.sub(force_name, 1, 16) and string.sub(force_name, 1, 16) == 'ancient-friendly' then
elseif force_name and string.sub(force_name, 1, 16) == 'ancient-friendly' then
if e.name == 'oil-refinery' then
e.set_recipe('advanced-oil-processing')
end

View File

@ -11,8 +11,12 @@ local _inspect = require 'utils.inspect'.inspect
local SurfacesCommon = require 'maps.pirates.surfaces.common'
local Public = {}
local enum = {
DEFAULT = 'Default',
SLOT_EXTRA_HOLD = 5,
SLOT_MORE_POWER = 6,
SLOT_REROLL_PRICES = 7,
}
Public.enum = enum
@ -95,7 +99,7 @@ Public.Data.input_chests = {
Public.Data.surfacename_rendering_pos = {x = -0.5, y = -15}
Public.market_price_scale = 300
Public.cabin_shop_data = {
{
@ -111,8 +115,20 @@ Public.cabin_shop_data = {
offer = {type='give-item', item = 'uranium-238', count = 10},
},
{
price = {{'coin', 800}, {'explosives', 4}},
offer = {type='give-item', item = 'cliff-explosives', count = 1},
price = {{'coin', 1000}, {'explosives', 5}},
offer = {type='give-item', item = 'cliff-explosives', count = 5},
},
{
price = {}, -- price set later
offer = {type='nothing', effect_description={'pirates.market_description_upgrade_hold'}}
},
{
price = {}, -- price set later
offer = {type='nothing', effect_description={'pirates.market_description_upgrade_power'}}
},
{
price = {{'coin', 100}, {'raw-fish', 1}},
offer = {type='nothing', effect_description={'pirates.market_description_reroll_prices'}}
},
--disabled now that we can wait after any destination:
-- {
@ -265,7 +281,8 @@ function Public.create_cabin_surface()
e.destructible = false
e.minable = false
e.rotatable = false
for _, offer in pairs(Public.cabin_shop_data) do
for i, offer in pairs(Public.cabin_shop_data) do
offer.price = Public.get_market_random_price(i) or offer.price
e.add_market_item(offer)
end
end
@ -333,4 +350,29 @@ function Public.chunk_structures()
return nil
end
function Public.handle_purchase(market, slot)
local offers = market.get_market_items()
market.clear_market_items()
for i, offer in pairs(offers) do
if i == slot or slot == enum.SLOT_REROLL_PRICES then
offer.price = Public.get_market_random_price(i) or offer.price
end
market.add_market_item(offer)
end
end
function Public.get_market_random_price(slot)
local memory = Memory.get_crew_memory()
if slot == enum.SLOT_EXTRA_HOLD then
local tier = memory.hold_surface_count
return Common.pick_random_price(tier, Public.market_price_scale, math.min(0.8, 0.05 + tier * 0.2))
elseif slot == enum.SLOT_MORE_POWER then
local tier = memory.boat.EEI_stage
return Common.pick_random_price(tier, 0.5*Public.market_price_scale, math.min(0.8, 0.05 + tier * 0.2))
end
return nil
end
return Public

View File

@ -19,7 +19,7 @@ local Public = {}
Public.Data = {}
Public.Data.display_names = {{'pirates.location_displayname_dock_1'}}
Public.Data.discord_emoji = CoreData.comfy_emojis.smolfish
Public.Data.discord_emoji = CoreData.comfy_emojis.hype
Public.Data.width = 296
Public.Data.height = 98

View File

@ -0,0 +1,233 @@
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
local Memory = require 'maps.pirates.memory'
local Math = require 'maps.pirates.math'
local Common = require 'maps.pirates.common'
local Utils = require 'maps.pirates.utils_local'
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 Public = {}
Public.Data = require 'maps.pirates.surfaces.islands.cave.data'
-- Code imported from cave_miner_v2 scenario for cave generation
--lab-dark-1 > position has been copied
--lab-dark-2 > position has been visited
function Public.reveal(cave_miner, surface, source_surface, position, brushsize)
local source_tile = source_surface.get_tile(position)
if not source_tile.valid then return end
if source_tile.name == 'lab-dark-2' then return end
local tiles = {}
local copied_tiles = {}
local i = 0
local brushsize_square = brushsize ^ 2
local surface_name_decoded = SurfacesCommon.decode_surface_name(surface.name)
local chunk_destination_index = surface_name_decoded.destination_index
local memory = Memory.get_crew_memory()
local destination = memory.destinations[chunk_destination_index]
local terraingen_coordinates_offset = destination.static_params.terraingen_coordinates_offset
-- TODO: use radius search for "find_tiles_filtered" instead to avoid the check?
for _, tile in pairs(source_surface.find_tiles_filtered({area = {{position.x - brushsize, position.y - brushsize}, {position.x + brushsize, position.y + brushsize}}})) do
local tile_position = tile.position
if tile.name ~= 'lab-dark-2' and tile.name ~= 'lab-dark-1' and (position.x - tile_position.x) ^ 2 + (position.y - tile_position.y) ^ 2 < brushsize_square then
i = i + 1
copied_tiles[i] = {name = 'lab-dark-1', position = tile.position}
-- Avoid re-exploring these areas as they have been already revealed when map was loaded
-- Revealed areas when map gets loaded are: river and entrance (beach with sand)
local true_pos = Utils.psum{tile_position, {1, terraingen_coordinates_offset}}
true_pos = Utils.psum{true_pos, {x = 0.5, y = 0.5}}
local d = true_pos.x ^ 2 + true_pos.y ^ 2
local boat_height = Math.max(BoatData.height, 15) -- even if boat height is smaller, we need to be at least 10+ just so formulas below play out nicely
local spawn_radius = boat_height + 15
-- local entrance_radius = boat_height + 45
local river_width = boat_height + 40
-- Don't copy river upon which ship arrives + ship entrance
if not (true_pos.x < 0 and d >= spawn_radius ^ 2 and Math.abs(2 * true_pos.y) < river_width) then
tiles[i] = {name = tile.name, position = tile.position}
end
end
end
surface.set_tiles(tiles, true, false, false, false)
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.force.index == 2 then
e.active = true
table.insert(cave_miner.reveal_queue, {entity.type, entity.position.x, entity.position.y})
end
entity.destroy()
end
end
source_surface.set_tiles({{name = 'lab-dark-2', position = position}}, false)
source_surface.request_to_generate_chunks(position, 3)
end
function Public.roll_source_surface(destination_data)
local map_gen_settings = {
['water'] = 0,
['starting_area'] = 1,
['cliff_settings'] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0},
['default_enable_all_autoplace_controls'] = false,
['autoplace_settings'] = {
['entity'] = {treat_missing_as_default = false},
['tile'] = {treat_missing_as_default = false},
['decorative'] = {treat_missing_as_default = false}
},
autoplace_controls = {
['coal'] = {frequency = 0, size = 0, richness = 0},
['stone'] = {frequency = 0, size = 0, richness = 0},
['copper-ore'] = {frequency = 0, size = 0, richness = 0},
['iron-ore'] = {frequency = 0, size = 0, richness = 0},
['uranium-ore'] = {frequency = 0, size = 0, richness = 0},
['crude-oil'] = {frequency = 0, size = 0, richness = 0},
['trees'] = {frequency = 0, size = 0, richness = 0},
['enemy-base'] = {frequency = 0, size = 0, richness = 0}
},
}
local cave_miner = destination_data.dynamic_data.cave_miner
local island_surface_name = SurfacesCommon.decode_surface_name(destination_data.surface_name)
local cave_surface_name = SurfacesCommon.encode_surface_name(island_surface_name.crewid, island_surface_name.destination_index, island_surface_name.type, IslandEnum.enum.CAVE_SOURCE)
cave_miner.cave_surface = game.create_surface(cave_surface_name, map_gen_settings)
cave_miner.cave_surface.request_to_generate_chunks({x = 0, y = 0}, 2)
-- cave_miner.cave_surface.force_generate_chunk_requests() -- Figure out if this is needed at all since it causes issues
end
function Public.cleanup_cave_surface(destination_data)
local dynamic_data = destination_data.dynamic_data
if dynamic_data and dynamic_data.cave_miner and dynamic_data.cave_miner.cave_surface then
game.delete_surface(dynamic_data.cave_miner.cave_surface)
end
end
local biomes = {}
function biomes.void(args)
args.tiles[#args.tiles + 1] = {name = 'out-of-map', position = args.p}
end
function biomes.entrance(args, square_distance)
if square_distance < (BoatData.height + 40) ^ 2 then
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
else
args.tiles[#args.tiles + 1] = {name = 'water-shallow', position = args.p}
end
end
function biomes.river(args)
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
Public.Data.spawn_fish(args);
end
function Public.terrain(args)
local position = args.p
local d = position.x ^ 2 + position.y ^ 2
local boat_height = Math.max(BoatData.height, 15) -- even if boat height is smaller, we need to be at least 10+ just so formulas below play out nicely
local spawn_radius = boat_height + 15
local entrance_radius = boat_height + 45
local river_width = boat_height + 40
-- Spawn location for market
if d < spawn_radius ^ 2 then
biomes.void(args)
-- Cave entrance
elseif position.x < 0 and d < entrance_radius ^ 2 and Math.abs(2 * position.y) < river_width then
biomes.entrance(args, d)
-- River upon which ship arrives
elseif position.x < 0 and Math.abs(2 * position.y) < river_width then
biomes.river(args)
else
biomes.void(args)
end
-- fallback case when no tiles were placed
if #args.tiles == 0 then
args.tiles[#args.tiles + 1] = {name = 'dirt-7', position = args.p}
end
end
-- function Public.chunk_structures(args)
-- end
-- Launching rocket in caves sounds silly
-- function Public.generate_silo_setup_position(points_to_avoid)
-- end
local function on_player_changed_position(event)
if not event.player_index then return end
local player = game.players[event.player_index]
if not player.character then return end
if not player.character.valid then return end
local crew_id = Common.get_id_from_force_name(player.force.name)
if not crew_id then return end
Memory.set_working_id(crew_id)
local destination_data = Common.current_destination()
if destination_data.surface_name ~= player.surface.name then return end
if not (destination_data and destination_data.subtype == IslandEnum.enum.CAVE) then return end
local cave_miner = destination_data.dynamic_data.cave_miner
-- TODO: make more reliable way to get island surface
Public.reveal(cave_miner, player.surface, cave_miner.cave_surface, {x = Math.floor(player.position.x), y = Math.floor(player.position.y)}, 11)
local reveal = cave_miner.reveal_queue[1]
if not reveal then
return
end
local brush_size = 5
Public.reveal(cave_miner, player.surface, cave_miner.cave_surface, {x = reveal[2], y = reveal[3]}, brush_size)
table.remove(cave_miner.reveal_queue, 1)
end
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
return Public

View File

@ -0,0 +1,334 @@
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
local Memory = require 'maps.pirates.memory'
local Math = require 'maps.pirates.math'
local Common = require 'maps.pirates.common'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local GetNoise = require 'utils.get_noise'
local BoatData = require 'maps.pirates.structures.boats.sloop.data'
local Balance = require 'maps.pirates.balance'
local ShopCovered = require 'maps.pirates.shop.covered'
local Classes = require 'maps.pirates.roles.classes'
local Public = {}
Public.Data = require 'maps.pirates.surfaces.islands.cave.data'
-- Code imported from cave_miner_v2 scenario for cave generation
local function spawn_market(args, is_main)
is_main = is_main or false
local destination_data = Common.current_destination()
--if not (destination_data and destination_data.dynamic_data and destination_data.dynamic_data.cave_miner) then return end
if not (destination_data and destination_data.dynamic_data) then return end
local offers
if is_main then
offers = ShopCovered.market_generate_coin_offers(6)
if destination_data.static_params.class_for_sale then
offers[#offers+1] = {price={{'coin', Balance.class_cost(true)}}, offer={type="nothing", effect_description = {'pirates.market_description_purchase_class', Classes.display_form(destination_data.static_params.class_for_sale)}}}
end
offers[#offers+1] = {price = {{'coin', 200}}, offer = {type = 'give-item', item = 'small-lamp', count = 100}}
else
-- This doesn't really prevent markets spawning near each other, since markets aren't spawned immediately for a given chunk, but it helps a bit
local surface = destination_data.dynamic_data.cave_miner.cave_surface
local r = 64
if surface.count_entities_filtered({name = 'market', area = {{args.p.x - r, args.p.y - r}, {args.p.x + r, args.p.y + r}}}) > 0 then
return
end
offers = ShopCovered.market_generate_coin_offers(4)
end
args.specials[#args.specials + 1] = {name = 'market', position = args.p, offers = offers}
end
local function place_rock(args)
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
local biomes = {}
function biomes.oasis(args, noise)
local seed = args.seed
local position = args.p
if noise > 0.83 then
args.tiles[#args.tiles + 1] = {name = 'deepwater', position = args.p}
Public.Data.spawn_fish(args);
return
end
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
args.entities[#args.entities + 1] = {name = 'tree-04', position = args.p}
end
if Math.random(1, 50) == 1 then
args.entities[#args.entities + 1] = {name = 'crude-oil', position = args.p, amount = Balance.pick_default_oil_amount() * 2}
end
if noise < 0.73 then
place_rock(args)
end
end
function biomes.void(args)
args.tiles[#args.tiles + 1] = {name = 'out-of-map', position = args.p}
end
function biomes.pond_cave(args, noise)
local seed = args.seed
local position = args.p
local noise_2 = GetNoise('cm_ponds', position, seed)
if Math.abs(noise_2) > 0.60 then
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
Public.Data.spawn_fish(args);
return
end
if Math.abs(noise_2) > 0.25 then
place_rock(args)
return
end
if noise > -0.53 then
place_rock(args)
else
if Math.random(1, 512) == 1 then
spawn_market(args)
end
end
end
-- Spawn refers to the "middle of the map" where the market is located
function biomes.spawn(args, square_distance)
local seed = args.seed
local position = args.p
-- If coordinate iteration ever changes to xn instead of 0.5 + xn this will need to change
if Math.abs(position.x - 0.5) < 0.1 and Math.abs(position.y - 0.5) < 0.1 then
spawn_market(args, true)
end
local noise = GetNoise('decoratives', position, seed)
if Math.abs(noise) > 0.60 and square_distance < 900 and square_distance > 10 then
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
Public.Data.spawn_fish(args);
return
end
if square_distance > 100 then
place_rock(args)
end
end
function biomes.ocean(args, noise)
if noise > 0.66 then
args.tiles[#args.tiles + 1] = {name = 'deepwater', position = args.p}
Public.Data.spawn_fish(args);
return
end
if noise > 0.63 then
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
Public.Data.spawn_fish(args);
return
end
place_rock(args)
end
function biomes.worm_desert(args, noise)
local seed = args.seed
local position = args.p
local memory = Memory.get_crew_memory()
if noise > -0.65 then
place_rock(args)
return
end
local i = Math.floor((GetNoise('decoratives', position, seed) * 8) % 3) + 1
args.tiles[#args.tiles + 1] = {name = 'sand-' .. i, position = args.p}
if Math.random(1, 64) == 1 then
local name = Common.get_random_worm_type(memory.evolution_factor)
local force = memory.enemy_force_name
args.entities[#args.entities + 1] = {name = name, position = args.p, force = force}
return
end
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}
return
end
end
if Math.random(1, 256) == 1 then
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
end
end
function biomes.cave(args, square_distance)
local seed = args.seed
local position = args.p
local memory = Memory.get_crew_memory()
local noise_cave_rivers1 = GetNoise('cave_rivers_2', position, seed + 100000)
if Math.abs(noise_cave_rivers1) < 0.025 then
local noise_cave_rivers2 = GetNoise('cave_rivers_3', position, seed + 200000)
if noise_cave_rivers2 > 0 then
args.tiles[#args.tiles + 1] = {name = 'water-shallow', position = args.p}
Public.Data.spawn_fish(args);
return
end
end
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
spawn_market(args)
end
end
args.tiles[#args.tiles + 1] = {name = 'dirt-' .. Math.floor(no_rocks_2 * 16) % 4 + 3, position = args.p}
return
end
if Math.abs(no_rocks_2) < 0.05 then
return
end
local noise_rock = GetNoise('small_caves', position, seed)
if noise_rock < 0.6 then
place_rock(args)
if Math.random(1, 512) == 1 then
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
end
return
end
if square_distance < 4096 then
return
end
if Math.random(1, 4096) == 1 then
spawn_market(args)
return
end
if Math.random(1, 64) == 1 then
local name
if Math.random(1, 2) == 1 then
name = 'biter-spawner'
else
name = 'spitter-spawner'
end
args.entities[#args.entities + 1] = {name = name, position = args.p, force = memory.enemy_force_name}
return
end
if Math.random(1, 64) == 1 then
local name = Common.get_random_worm_type(memory.evolution_factor)
local force = memory.enemy_force_name
args.entities[#args.entities + 1] = {name = name, position = args.p, force = force}
return
end
end
local function get_biome(args)
local position = args.p
local d = position.x ^ 2 + position.y ^ 2
local boat_height = Math.max(BoatData.height, 15) -- even if boat height is smaller, we need to be at least 10+ just so formulas below play out nicely
local spawn_radius = boat_height + 15
local entrance_radius = boat_height + 45
local river_width = boat_height + 40
-- Spawn location for market
if d < spawn_radius ^ 2 then
return biomes.spawn, d
end
-- River upon which ship arrives + ship entrance
if position.x < 0 and 2 * Math.abs(position.y) < river_width then
return biomes.void
end
-- Prevent cave expansion in west direction
-- NOTE: although "river_width ^ 2 - entrance_radius ^ 2" should never be "< 0", it's a small safe check
-- NOTE: the complex calculation here calculates wanted intersection of river and spawn area (or in other words line and circle intersection)
if position.x < 0 and -position.x + (river_width - Math.sqrt(Math.max(0, river_width ^ 2 - entrance_radius ^ 2))) > Math.abs(2 * position.y) then
return biomes.void
end
-- Actual cave generation below
local cm_ocean = GetNoise('cm_ocean', position, args.seed + 100000)
if cm_ocean > 0.6 then
return biomes.ocean, cm_ocean
end
local noise = GetNoise('cave_miner_01', position, args.seed)
local abs_noise = Math.abs(noise)
if abs_noise < 0.075 then
return biomes.cave, d
end
if abs_noise > 0.25 then
noise = GetNoise('cave_rivers', position, args.seed)
if noise > 0.72 then
return biomes.oasis, noise
end
if cm_ocean < -0.6 then
return biomes.worm_desert, cm_ocean
end
if noise < -0.5 then
return biomes.pond_cave, noise
end
end
noise = GetNoise('cave_miner_02', position, args.seed)
if Math.abs(noise) < 0.085 then
return biomes.cave, d
end
return biomes.void
end
function Public.terrain(args)
local tiles_placed = #args.tiles
local biome, square_distance, noise = get_biome(args)
biome(args, square_distance, noise)
-- fallback case when tile wasn't placed
if tiles_placed == #args.tiles then
args.tiles[#args.tiles + 1] = {name = 'dirt-7', position = args.p}
end
end
-- Finding a spot for structures is very hard (it might cause structures to spawn in weird locations, like ship)
-- function Public.chunk_structures(args)
-- end
-- Launching rocket in caves sounds silly (as well as hard to pick position for rocket)
-- function Public.generate_silo_setup_position(points_to_avoid)
-- end
return Public

View File

@ -0,0 +1,37 @@
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
local Public = {}
Public.display_names = {{'pirates.location_displayname_cave_1'}}
Public.terraingen_frame_width = 640
Public.terraingen_frame_height = 640
Public.static_params_default = {
default_decoratives = true,
base_starting_treasure = 1000,
base_starting_rock_material = 800,
base_starting_wood = 1200,
base_starting_treasure_maps = 0,
starting_time_of_day = 0.43,
daynightcycletype = 1,
brightness_visual_weights = {0.92, 0.92, 0.92},
min_brightness = 0.08,
}
function Public.base_ores()
return {
['copper-ore'] = 0.7,
['iron-ore'] = 5.9,
['coal'] = 4.4,
['stone'] = 1.0,
['uranium-ore'] = 0.5,
}
end
function Public.spawn_fish(args)
if math.random(1, 16) == 1 then
args.entities[#args.entities + 1] = {name = 'fish', position = args.p}
end
end
return Public

View File

@ -8,28 +8,27 @@ local Structures = require 'maps.pirates.structures.structures'
local Common = require 'maps.pirates.common'
-- local Utils = require 'maps.pirates.utils_local'
-- local Ores = require 'maps.pirates.ores'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local _inspect = require 'utils.inspect'.inspect
local Public = {}
local enum = {
STANDARD = '1',
FIRST = '2',
WALKWAYS = '3',
RED_DESERT = '4',
RADIOACTIVE = '5',
STANDARD_VARIANT = '6',
HORSESHOE = '7',
SWAMP = '8',
MAZE = '9',
}
Public.enum = enum
Public.enum = IslandEnum.enum
function Public.place_water_tile(args)
function Public.place_water_tile(args, place_green_water)
local water_names = {}
if place_green_water then
water_names[#water_names+1] = 'water-green'
water_names[#water_names+1] = 'deepwater-green'
else
water_names[#water_names+1] = 'water'
water_names[#water_names+1] = 'deepwater'
end
if args.static_params and args.static_params.deepwater_terraingenframe_xposition and args.p.x <= args.static_params.deepwater_terraingenframe_xposition - 0.5
then
args.tiles[#args.tiles + 1] = {name = 'deepwater', position = args.p}
args.tiles[#args.tiles + 1] = {name = water_names[2], position = args.p}
local fishrng = Math.random(350)
if fishrng == 350 then
@ -42,7 +41,7 @@ function Public.place_water_tile(args)
local height_noise = args.noise_generator['height'](args.p)
if height_noise < 0 then
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
args.tiles[#args.tiles + 1] = {name = water_names[1], position = args.p}
local fishrng = Math.random(350)
if fishrng == 350 then

View File

@ -0,0 +1,21 @@
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
local Public = {}
local enum = {
STANDARD = '1',
FIRST = '2',
WALKWAYS = '3',
RED_DESERT = '4',
RADIOACTIVE = '5',
STANDARD_VARIANT = '6',
HORSESHOE = '7',
SWAMP = '8',
MAZE = '9',
CAVE = '10',
CAVE_SOURCE = '11', -- Used as extra layer for cave island
}
Public.enum = enum
return Public

View File

@ -9,7 +9,6 @@ local Boats = require 'maps.pirates.structures.boats.boats'
local Common = require 'maps.pirates.common'
local CoreData = require 'maps.pirates.coredata'
local Utils = require 'maps.pirates.utils_local'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local Hunt = require 'maps.pirates.surfaces.islands.hunt'
local Ores = require 'maps.pirates.ores'
local Quest = require 'maps.pirates.quest'
@ -17,10 +16,10 @@ local _inspect = require 'utils.inspect'.inspect
local Token = require 'utils.token'
local Task = require 'utils.task'
local QuestStructures = require 'maps.pirates.structures.quest_structures.quest_structures'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Public = {}
local enum = IslandsCommon.enum
Public.enum = enum
local enum = IslandEnum.enum
Public[enum.FIRST] = require 'maps.pirates.surfaces.islands.first.first'
Public[enum.STANDARD] = require 'maps.pirates.surfaces.islands.standard.standard'
@ -31,6 +30,8 @@ Public[enum.RED_DESERT] = require 'maps.pirates.surfaces.islands.red_desert.red_
Public[enum.HORSESHOE] = require 'maps.pirates.surfaces.islands.horseshoe.horseshoe'
Public[enum.SWAMP] = require 'maps.pirates.surfaces.islands.swamp.swamp'
Public[enum.MAZE] = require 'maps.pirates.surfaces.islands.maze.maze'
Public[enum.CAVE] = require 'maps.pirates.surfaces.islands.cave.cave'
Public[enum.CAVE_SOURCE] = require 'maps.pirates.surfaces.islands.cave.cave_source' -- Used as extra layer for cave island
Public['IslandsCommon'] = require 'maps.pirates.surfaces.islands.common'
@ -274,6 +275,8 @@ function Public.spawn_silo_setup(points_to_avoid)
local subtype = destination.subtype
local force = memory.force
if not Public[subtype].generate_silo_setup_position then return end
local p_silo = Public[subtype].generate_silo_setup_position(points_to_avoid)
if not p_silo then return end
-- log(string.format("placing silo at x=%f, y = %f", p_silo.x, p_silo.y))

View File

@ -13,7 +13,7 @@ Public.terraingen_frame_width = 700
Public.terraingen_frame_height = 700
Public.static_params_default = {
starting_time_of_day = 0.45,
brightness_visual_weights = {0.8, 0.8, 0.8},
brightness_visual_weights = {0.8, 0.6, 0.8},
daynightcycletype = 4,
min_brightness = 0.05,
base_starting_treasure = 1000,

View File

@ -12,6 +12,7 @@ local Utils = require 'maps.pirates.utils_local'
local _inspect = require 'utils.inspect'.inspect
-- local Ores = require 'maps.pirates.ores'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
-- local Hunt = require 'maps.pirates.surfaces.islands.hunt'
local Public = {}
@ -39,10 +40,10 @@ function Public.terrain(args)
local p = args.p
if IslandsCommon.place_water_tile(args) then return end
if IslandsCommon.place_water_tile(args, true) then return end
if noises.height(p) < 0 then
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
args.tiles[#args.tiles + 1] = {name = 'water-green', position = args.p}
return
end
@ -108,7 +109,7 @@ function Public.terrain(args)
args.entities[#args.entities + 1] = {name = 'stone', position = args.p, amount = 1000}
elseif noises.ore(p) < 0.005 and noises.ore(p) > -0.005 then
if noises.ore(p) > 0 then
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 10}
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 20}
else
args.entities[#args.entities + 1] = {name = 'copper-ore', position = args.p, amount = 100}
end
@ -129,7 +130,7 @@ function Public.chunk_structures(args)
-- we need some indestructible spawners, because otherwise you can clear, stay here forever, make infinite resources...
spawners_indestructible = noises.farness(p) > 0.63,
-- spawners_indestructible = false,
density_perchunk = 25 * Math.slopefromto(noises.farness(p), 0.3, 1)^2 * args.biter_base_density_scale,
density_perchunk = 20 * Math.slopefromto(noises.farness(p), 0.3, 1.08)^2 * args.biter_base_density_scale,
}
end
@ -269,7 +270,7 @@ local function radioactive_tick()
local tickinterval = 60
if destination.subtype == IslandsCommon.enum.RADIOACTIVE then
if destination.subtype == IslandEnum.enum.RADIOACTIVE then
-- faster evo (doesn't need difficulty scaling as higher difficulties have higher base evo):
local extra_evo = 0.22 * tickinterval/60 / Balance.expected_time_on_island()
Common.increment_evo(extra_evo)

View File

@ -10,7 +10,7 @@ local Public = {}
Public.display_names = {{'pirates.location_displayname_red_desert_1'}}
Public.discord_emoji = CoreData.comfy_emojis.mjau
Public.discord_emoji = CoreData.comfy_emojis.hype
Public.terraingen_frame_width = 700
Public.terraingen_frame_height = 700

View File

@ -12,6 +12,7 @@ local Utils = require 'maps.pirates.utils_local'
local _inspect = require 'utils.inspect'.inspect
-- local Ores = require 'maps.pirates.ores'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Hunt = require 'maps.pirates.surfaces.islands.hunt'
local Public = {}
@ -81,9 +82,9 @@ function Public.terrain(args)
elseif rng < 0.001 then
args.entities[#args.entities + 1] = {name = 'medium-ship-wreck', position = args.p}
elseif rng < 0.0013 then
args.entities[#args.entities + 1] = {name = 'big-ship-wreck-2', position = args.p}
args.specials[#args.specials + 1] = {name = 'big-ship-wreck-2', position = args.p}
elseif rng < 0.0014 then
args.entities[#args.entities + 1] = {name = 'big-ship-wreck-1', position = args.p}
args.specials[#args.specials + 1] = {name = 'big-ship-wreck-1', position = args.p}
end
end
end
@ -117,23 +118,24 @@ function Public.terrain(args)
end
if noises.forest_abs_suppressed(p) < 0.8 and noises.mood(p) > -0.3 then
local amount = Math.ceil(70 * noises.height(p) * Balance.island_richness_avg_multiplier() * Math.random_float_in_range(0.9, 1.1))
if noises.height(p) > 0.27 then
if noises.ore(p) > 1.5 then
local name = 'iron-ore'
if (args.p.x + args.p.y) % 2 < 1 then
name = 'copper-ore'
end
args.entities[#args.entities + 1] = {name = name, position = args.p, amount = 20}
args.entities[#args.entities + 1] = {name = name, position = args.p, amount = amount}
elseif noises.ore(p) < -1.6 then
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 20}
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = amount}
elseif noises.ore(p) < 0.041 and noises.ore(p) > -0.041 then
args.entities[#args.entities + 1] = {name = 'stone', position = args.p, amount = 10}
args.entities[#args.entities + 1] = {name = 'stone', position = args.p, amount = amount}
end
elseif noises.height(p) < 0.19 then
if noises.ore(p) > 2.1 then
args.entities[#args.entities + 1] = {name = 'copper-ore', position = args.p, amount = 10}
args.entities[#args.entities + 1] = {name = 'copper-ore', position = args.p, amount = amount}
elseif noises.ore(p) < -2.1 then
args.entities[#args.entities + 1] = {name = 'iron-ore', position = args.p, amount = 10}
args.entities[#args.entities + 1] = {name = 'iron-ore', position = args.p, amount = amount}
-- elseif noises.ore(p) < 0.010 and noises.ore(p) > -0.010 then
-- args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 5}
end
@ -226,7 +228,7 @@ local function red_desert_tick()
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
if destination.subtype == IslandsCommon.enum.RED_DESERT then
if destination.subtype == IslandEnum.enum.RED_DESERT then
if memory.boat and memory.boat.surface_name and memory.boat.surface_name == destination.surface_name then
Public.underground_worms_ai()

View File

@ -10,6 +10,7 @@ local Common = require 'maps.pirates.common'
local _inspect = require 'utils.inspect'.inspect
local Ores = require 'maps.pirates.ores'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Hunt = require 'maps.pirates.surfaces.islands.hunt'
local Public = {}
@ -129,8 +130,8 @@ function Public.chunk_structures(args)
placeable = noises.farness(p) > 0.3,
-- spawners_indestructible = noises.farness(p) > 0.75,
spawners_indestructible = false,
spawners_density_perchunk = 81 * Math.slopefromto(noises.mood(p), 0.7, 0.5) * Math.slopefromto(noises.farness(p), 0.35, 1)^(1.8) * args.biter_base_density_scale,
worms_density_perchunk = 27 * Math.slopefromto(noises.mood(p), 0.7, 0.5) * Math.slopefromto(noises.farness(p), 0.25, 1)^(1.8) * args.biter_base_density_scale,
spawners_density_perchunk = 54 * Math.slopefromto(noises.mood(p), 0.7, 0.5) * Math.slopefromto(noises.farness(p), 0.35, 1.1)^(1.8) * args.biter_base_density_scale,
worms_density_perchunk = 18 * Math.slopefromto(noises.mood(p), 0.7, 0.5) * Math.slopefromto(noises.farness(p), 0.25, 1.1)^(1.8) * args.biter_base_density_scale,
}
end
@ -187,7 +188,7 @@ local function swamp_tick()
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
if destination.subtype and destination.subtype == IslandsCommon.enum.SWAMP then
if destination.subtype == IslandEnum.enum.SWAMP then
if memory.boat and memory.boat.surface_name and memory.boat.surface_name == destination.surface_name then
local surface = game.surfaces[destination.surface_name]
if not (surface and surface.valid) then return end

View File

@ -3,7 +3,7 @@
local Memory = require 'maps.pirates.memory'
local Math = require 'maps.pirates.math'
-- local Balance = require 'maps.pirates.balance'
local Balance = require 'maps.pirates.balance'
-- local Structures = require 'maps.pirates.structures.structures'
local Common = require 'maps.pirates.common'
local CoreData = require 'maps.pirates.coredata'
@ -12,6 +12,7 @@ local _inspect = require 'utils.inspect'.inspect
-- local Data = require 'maps.pirates.surfaces.islands.walkways.data'
local Ores = require 'maps.pirates.ores'
local IslandsCommon = require 'maps.pirates.surfaces.islands.common'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Hunt = require 'maps.pirates.surfaces.islands.hunt'
local Public = {}
@ -75,7 +76,8 @@ function Public.terrain(args)
end
if noises.height(p) > 0.12 and noises.walkways(p) < 0.1 and noises.rock_abs(p) < 0.07 then
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 14}
local amount = Math.ceil(150 * Math.min(noises.height(p), 0.2) * Balance.island_richness_avg_multiplier() * Math.random_float_in_range(0.8, 1.2))
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = amount}
end
else
@ -91,7 +93,7 @@ function Public.chunk_structures(args)
return {
placeable = noises.walkways(p) < 0.30,
density_perchunk = 20 * (noises.farness(p) - 0.1)^3 * args.biter_base_density_scale,
density_perchunk = 15 * (noises.farness(p) - 0.1)^3 * args.biter_base_density_scale,
spawners_indestructible = true,
}
end
@ -144,7 +146,7 @@ local function walkways_tick()
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
if destination.subtype and destination.subtype == IslandsCommon.enum.WALKWAYS then
if destination.subtype == IslandEnum.enum.WALKWAYS then
for _, player in pairs(game.connected_players) do
if player.force.name == memory.force_name and player.surface == game.surfaces[destination.surface_name] and player.character and player.character.valid and game.surfaces[destination.surface_name].get_tile(player.position).name == 'water-shallow' then
player.character.damage(12, game.forces['environment'], 'fire')

View File

@ -22,6 +22,7 @@ local ShopMerchants = require 'maps.pirates.shop.merchants'
local SurfacesCommon = require 'maps.pirates.surfaces.common'
-- local Roles = require 'maps.pirates.roles.roles'
local Classes = require 'maps.pirates.roles.classes'
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
local Server = require 'utils.server'
@ -116,9 +117,19 @@ function Public.on_surface_generation(destination)
destination.dynamic_data.silocharged = false
destination.dynamic_data.rocketlaunched = false
if subtype ~= Islands.enum.STANDARD and subtype ~= Islands.enum.STANDARD_VARIANT and subtype ~= Islands.enum.RADIOACTIVE and subtype ~= Islands.enum.RED_DESERT then
if subtype ~= IslandEnum.enum.STANDARD and subtype ~= IslandEnum.enum.STANDARD_VARIANT and subtype ~= IslandEnum.enum.RADIOACTIVE and subtype ~= IslandEnum.enum.RED_DESERT then
destination.dynamic_data.hidden_ore_remaining_abstract = Utils.deepcopy(destination.static_params.abstract_ore_amounts)
end
if subtype == IslandEnum.enum.CAVE then
if not destination.dynamic_data.cave_miner then
destination.dynamic_data.cave_miner = {}
destination.dynamic_data.cave_miner.reveal_queue = {}
destination.dynamic_data.cave_miner.cave_surface = nil
Islands[IslandEnum.enum.CAVE].roll_source_surface(destination)
end
end
destination.dynamic_data.wood_remaining = destination.static_params.starting_wood
destination.dynamic_data.rock_material_remaining = destination.static_params.starting_rock_material
destination.dynamic_data.treasure_remaining = destination.static_params.starting_treasure
@ -162,10 +173,13 @@ function Public.destination_on_collide(destination)
if destination.subtype == Islands.enum.RADIOACTIVE then
if destination.subtype == IslandEnum.enum.RADIOACTIVE then
Common.parrot_speak(memory.force, {'pirates.parrot_radioactive_tip_1'})
else
elseif destination.subtype == IslandEnum.enum.CAVE then
Common.parrot_speak(memory.force, {'pirates.parrot_cave_tip_1'})
else
local scheduled_raft_raids
-- temporarily placed this back here, as moving it to shorehit broke things:
local playercount = Common.activecrewcount()
@ -192,39 +206,42 @@ function Public.destination_on_collide(destination)
end
end
if memory.overworldx > 200 then
scheduled_raft_raids = {}
local times = {600, 360, 215, 210, 120, 30, 10, 5}
for i = 1, #times do
local t = times[i]
if Math.random(6) == 1 and #scheduled_raft_raids < 6 then
-- Currently biter boats don't spawn properly for cave island, so disabling it for now
if destination.subtype ~= IslandEnum.enum.CAVE then
if memory.overworldx > 200 then
scheduled_raft_raids = {}
local times = {600, 360, 215, 210, 120, 30, 10, 5}
for i = 1, #times do
local t = times[i]
if Math.random(6) == 1 and #scheduled_raft_raids < 6 then
scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_evo = max_evo}
-- scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_bonus_evolution = 0.52}
end
end
elseif memory.overworldx == 200 then
local times
if playercount <= 2 then
times = {1, 5, 10, 15, 20}
elseif playercount <= 8 then
times = {1, 5, 10, 15, 20, 25}
elseif playercount <= 15 then
times = {1, 5, 10, 15, 20, 25, 30}
elseif playercount <= 21 then
times = {1, 5, 10, 15, 20, 25, 30, 35}
else
times = {1, 5, 10, 15, 20, 25, 30, 35, 40}
end
scheduled_raft_raids = {}
for _, t in pairs(times) do
-- scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_bonus_evolution = 0.62}
scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_evo = max_evo}
-- scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_bonus_evolution = 0.52}
end
end
elseif memory.overworldx == 200 then
local times
if playercount <= 2 then
times = {1, 5, 10, 15, 20}
elseif playercount <= 8 then
times = {1, 5, 10, 15, 20, 25}
elseif playercount <= 15 then
times = {1, 5, 10, 15, 20, 25, 30}
elseif playercount <= 21 then
times = {1, 5, 10, 15, 20, 25, 30, 35}
else
times = {1, 5, 10, 15, 20, 25, 30, 35, 40}
end
scheduled_raft_raids = {}
for _, t in pairs(times) do
-- scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_bonus_evolution = 0.62}
scheduled_raft_raids[#scheduled_raft_raids + 1] = {timeinseconds = t, max_evo = max_evo}
end
destination.static_params.scheduled_raft_raids = scheduled_raft_raids
end
destination.static_params.scheduled_raft_raids = scheduled_raft_raids
end
end
if memory.overworldx == 40*5 then
@ -256,17 +273,21 @@ function Public.destination_on_arrival(destination)
destination.dynamic_data.rocketsiloenergyneeded = Balance.silo_energy_needed_MJ() * 1000000
destination.dynamic_data.rocketcoalreward = Balance.rocket_launch_fuel_reward()
if destination.subtype == Islands.enum.RADIOACTIVE then
if destination.subtype == IslandEnum.enum.RADIOACTIVE then
destination.dynamic_data.time_remaining = -1
elseif destination.subtype == Islands.enum.MAZE then --more time
elseif destination.subtype == IslandEnum.enum.MAZE then --more time
destination.dynamic_data.time_remaining = Math.ceil(1.05 * Balance.max_time_on_island())
else
destination.dynamic_data.time_remaining = Math.ceil(Balance.max_time_on_island())
end
if destination.subtype ~= Islands.enum.FIRST and destination.subtype ~= Islands.enum.RADIOACTIVE and destination.destination_index ~= 2 then
if destination.subtype ~= IslandEnum.enum.FIRST and destination.subtype ~= IslandEnum.enum.RADIOACTIVE and destination.destination_index ~= 2 then
-- if not destination.overworld_position.x ~= Common.first_cost_to_leave_macrox * 40 then
Quest.initialise_random_quest()
if destination.subtype == IslandEnum.enum.CAVE then
Quest.initialise_random_cave_island_quest()
else
Quest.initialise_random_quest()
end
-- else
-- if _DEBUG then
-- Quest.initialise_random_quest()
@ -278,12 +299,12 @@ function Public.destination_on_arrival(destination)
Common.set_evo(base_evo)
destination.dynamic_data.evolution_accrued_leagues = base_evo
destination.dynamic_data.evolution_accrued_time = 0
if destination.subtype == Islands.enum.RED_DESERT then
if destination.subtype == IslandEnum.enum.RED_DESERT then
destination.dynamic_data.evolution_accrued_sandwurms = 0
else
destination.dynamic_data.evolution_accrued_nests = 0
end
if destination.subtype ~= Islands.enum.RADIOACTIVE then
if destination.subtype ~= IslandEnum.enum.RADIOACTIVE then
destination.dynamic_data.evolution_accrued_silo = 0
end
@ -291,8 +312,8 @@ function Public.destination_on_arrival(destination)
memory.scripted_unit_groups = {}
memory.floating_pollution = 0
if destination.subtype == Islands.enum.RADIOACTIVE then
Islands[Islands.enum.RADIOACTIVE].spawn_structures()
if destination.subtype == IslandEnum.enum.RADIOACTIVE then
Islands[IslandEnum.enum.RADIOACTIVE].spawn_structures()
end
-- -- invulnerable bases on islands 21-25
-- if memory.overworldx >= 21 and memory.overworldx < 25 then
@ -323,7 +344,7 @@ function Public.destination_on_arrival(destination)
local name = destination.static_params.name and destination.static_params.name or 'NameNotFound'
local message = {'pirates.approaching_destination', memory.destinationsvisited_indices and #memory.destinationsvisited_indices or 0, name}
if not (#memory.destinationsvisited_indices and #memory.destinationsvisited_indices == 1) then --don't need to notify for the first island
Server.to_discord_embed_raw({'',(destination.static_params.discord_emoji or CoreData.comfy_emojis.wut) .. '[' .. memory.name .. '] Approaching ', name, ', ' .. memory.overworldx .. ' leagues.'}, true)
Server.to_discord_embed_raw({'',(destination.static_params.discord_emoji or CoreData.comfy_emojis.hype) .. '[' .. memory.name .. '] Approaching ', name, ', ' .. memory.overworldx .. ' leagues.'}, true)
end
-- if destination.static_params.name == 'Dock' then
-- message = message .. ' ' .. 'New trades are available in the Captain\'s Store.'
@ -349,8 +370,18 @@ function Public.destination_on_arrival(destination)
end
end
if (memory.overworldx >= Balance.quest_structures_first_appear_at and destination.subtype ~= IslandEnum.enum.RADIOACTIVE) or _DEBUG then
local class_for_sale = Classes.generate_class_for_sale()
destination.static_params.class_for_sale = class_for_sale
end
-- Caves won't have these fancy things for now, because starting place for this island is so small, weird stuff happens (like quest structure spawning on ship)
if destination.subtype == IslandEnum.enum.CAVE then
return
end
-- game.print('spawning silo')
if destination.subtype ~= Islands.enum.RADIOACTIVE then
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}
@ -359,10 +390,7 @@ function Public.destination_on_arrival(destination)
Islands.spawn_ores_on_arrival(destination, points_to_avoid)
if (memory.overworldx >= Balance.quest_structures_first_appear_at and destination.subtype ~= Islands.enum.RADIOACTIVE) or _DEBUG then
local class_for_sale = Classes.generate_class_for_sale()
destination.static_params.class_for_sale = class_for_sale
if (memory.overworldx >= Balance.quest_structures_first_appear_at and destination.subtype ~= IslandEnum.enum.RADIOACTIVE) or _DEBUG then
local covered = Islands.spawn_quest_structure(destination, points_to_avoid)
if covered then
points_to_avoid[#points_to_avoid + 1] = {x = covered.x, y = covered.y, r = 25}
@ -372,7 +400,7 @@ function Public.destination_on_arrival(destination)
Islands.spawn_treasure_maps(destination, points_to_avoid)
Islands.spawn_ghosts(destination, points_to_avoid)
if destination.subtype and destination.subtype == Islands.enum.MAZE then
if destination.subtype == IslandEnum.enum.MAZE then
local force = memory.force
force.manual_mining_speed_modifier = 1
end
@ -389,7 +417,7 @@ function Public.destination_on_departure(destination)
Common.parrot_speak(memory.force, {'pirates.parrot_kraken_warning'})
end
if destination.subtype and destination.subtype == Islands.enum.MAZE then
if destination.subtype and destination.subtype == IslandEnum.enum.MAZE then
local force = memory.force
force.manual_mining_speed_modifier = 3 --put back to normal
end
@ -418,7 +446,7 @@ function Public.destination_on_crewboat_hits_shore(destination)
Common.parrot_speak(memory.force, {'pirates.parrot_night_warning'})
end
if destination.subtype == Islands.enum.RADIOACTIVE then
if destination.subtype == IslandEnum.enum.RADIOACTIVE then
-- replace all miners, so that they sit on uranium properly:
local surface = game.surfaces[destination.surface_name]
local miners = surface.find_entities_filtered({name = 'electric-mining-drill'})
@ -430,11 +458,11 @@ function Public.destination_on_crewboat_hits_shore(destination)
end
Common.parrot_speak(memory.force, {'pirates.parrot_radioactive_tip_2'})
elseif destination.subtype == Islands.enum.MAZE and memory.overworldx == Common.maze_minimap_jam_league then
elseif destination.subtype == IslandEnum.enum.MAZE and memory.overworldx == Common.maze_minimap_jam_league then
Common.parrot_speak(memory.force, {'pirates.parrot_maze_tip_1'})
end
if memory.merchant_ships_unlocked or _DEBUG then
if (memory.merchant_ships_unlocked or _DEBUG) and destination.subtype ~= IslandEnum.enum.CAVE then
Islands.spawn_merchant_ship(destination)
ShopMerchants.generate_merchant_trades(destination.dynamic_data.merchant_market)
@ -484,7 +512,17 @@ function Public.generate_detailed_island_data(destination)
local p2 = {x = chunk_frameposition_topleft.x + x2, y = chunk_frameposition_topleft.y + y2}
local tiles3, entities3 = {}, {}
terrain_fn{p = p2, noise_generator = noise_generator, static_params = destination.static_params, tiles = tiles3, entities = entities3, decoratives = {}, seed = destination.seed, iconized_generation = true}
terrain_fn{
p = p2,
noise_generator = noise_generator,
static_params = destination.static_params,
tiles = tiles3,
entities = entities3,
decoratives = {},
specials = {},
seed = destination.seed,
iconized_generation = true
}
local tile = tiles3[1]
if modalcounts[tile.name] then
modalcounts[tile.name] = modalcounts[tile.name] + 1
@ -583,11 +621,21 @@ function Public.generate_detailed_island_data(destination)
-- get more precise understanding of left-hand shore
local xcorrection = 0
for ystep = -10, 10, 10 do
for xstep = 0,300,3 do
for xstep = 0, 300, 3 do
local x = leftboundary * 32 + 16 + xstep
local y = (topboundary*32 + bottomboundary*32)/2 + ystep
local tiles3 = {}
terrain_fn{p = {x = x, y = y}, noise_generator = noise_generator, static_params = destination.static_params, tiles = tiles3, entities = {}, decoratives = {}, seed = destination.seed, iconized_generation = true}
terrain_fn{
p = {x = x, y = y},
noise_generator = noise_generator,
static_params = destination.static_params,
tiles = tiles3,
entities = {},
decoratives = {},
specials = {},
seed = destination.seed,
iconized_generation = true
}
local tile = tiles3[1]
if (not Utils.contains(CoreData.water_tile_names, tile.name)) then
xcorrection = Math.max(xcorrection, xstep + Math.abs(ystep))
@ -713,6 +761,8 @@ function Public.clean_up(destination)
end
end
Islands[IslandEnum.enum.CAVE].cleanup_cave_surface(destination)
destination.dynamic_data = {}
memory.scripted_biters = nil