mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-03-17 20:58:13 +02:00
Merge pull request #244 from danielmartin0/develop
Merge in Pirate Ship now that the main branch has deflate
This commit is contained in:
commit
0d8c05f760
5
.gitignore
vendored
5
.gitignore
vendored
@ -2,3 +2,8 @@
|
||||
.history/
|
||||
.git/
|
||||
maps/biter_battles_v3/
|
||||
|
||||
|
||||
#==Mac ignores==
|
||||
# General
|
||||
.DS_Store
|
@ -110,6 +110,10 @@ require 'utils.freeplay'
|
||||
--![[Comfylatron has seized the Fish Train and turned it into a time machine]]--
|
||||
--require 'maps.chronosphere.main'
|
||||
|
||||
--![[Adventure as a crew of pirates]]--
|
||||
--NOTE: This scenario is intended to be used with utils.gui.group, utils.gui.poll, and utils.gui.score disabled
|
||||
--require 'maps.pirates.main'
|
||||
|
||||
--![[Launch rockets in increasingly harder getting worlds.]]--
|
||||
--require 'maps.journey.main'
|
||||
|
||||
|
48
locale/en/pirates.cfg
Normal file
48
locale/en/pirates.cfg
Normal file
@ -0,0 +1,48 @@
|
||||
[pirates]
|
||||
softmod_info_header_before_version_number==== Pirate Ship v
|
||||
softmod_info_header_after_version_number= ===
|
||||
softmod_info_body_1=News and voice chat: getcomfy.eu/discord
|
||||
|
||||
softmod_info_game_description_1=Game Description
|
||||
softmod_info_game_description_2=Set sail in this multiplayer scenario. Collect resources and fuel the ship in order to survive as many leagues as possible. The ship moves with code magic. Doubloons can be spent at docks and other markets, to upgrade players, upgrade the ship, and buy rare items. Each crew has a captain, who can perform actions such as deciding when the boat leaves.\n\nGame progression is significantly slowed down the smaller the crew.\n\n[font=default-bold]Win condition:[/font] Travel 1000 leagues.\n[font=default-bold]Lose condition:[/font] The ship runs out of fuel, or a cannon is destroyed.
|
||||
|
||||
softmod_info_bugs_1=Known issues
|
||||
softmod_info_bugs_2=• Very rarely (only observed once), the deck locomotive can disappear, and an admin needs to make a new one.
|
||||
|
||||
softmod_info_new_players_1=For New Players
|
||||
softmod_info_new_players_2=Mine coal and other resources and bring them to the ship to keep things going, or try asking the captain for more specific tasks.
|
||||
|
||||
softmod_info_tips_1=Features of the game that are hard to work out alone
|
||||
softmod_info_tips_2=• You 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 launches a rocket. This causes pollution and evo, but gives a reward of fuel and doubloons.\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 the amount it 'would have' made had it survived.)\n• Covered markets give back any plates spent to unlock them.\n• Lab productivity increases with each league.\n• The player who spent the longest as captain between leagues 0 and 1000 (exclusive) is written into the highscores table.\n• Logged-out players keep their items with them for a while — except 'important' items that are returned to the crew immediately.\n• Commands: /ccolor gives you a fun color. To manage your class, use /classinfo {classname}, /take {classname}, or /giveup. Captains also have /undock, /req, /officer, /plank.
|
||||
|
||||
softmod_info_updates_1=Development
|
||||
softmod_info_updates_2=Recent significant changes: Silo death is no longer a lose condition. Game made much easier for small crews. New islands and classes. The ship now shares power across each of its floors. Officers can now access chests in the captain's cabin directly.
|
||||
|
||||
softmod_info_credits_1=Credits
|
||||
softmod_info_credits_2=Pirate Ship designed and coded by thesixthroc. Comfy codebase and help from Gerkiz, Hanakocz and Mew @ Comfy Industries (https://getcomfy.eu). Some island structure blueprints contributed by Mattisso.\n\nContact us via Discord: https://getcomfy.eu/discord\n\n"Those white gloves. I'll never forget them 'till the day I die." - Dr. John
|
||||
softmod_info_credits_2_old=Softmod designed and written by thesixthroc. Comfy codebase help from Gerkiz, Hanakocz and Mew @ Comfy Industries (https://getcomfy.eu). Some island structure blueprints were contributed by Mattisso. Gold sprite by Clint Bellanger. Parrot sprites by @pixelthen.\n\n"Those white gloves. I'll never forget them 'till the day I die." - Dr. John
|
||||
|
||||
softmod_info_body_promote=by thesixthroc
|
||||
softmod_info_body_promote_old2=patreon.com/thesixthroc
|
||||
|
||||
softmod_info_body_clicky=Click to dismiss.
|
||||
|
||||
softmod_info_body_some_old_stuff="Those white gloves. I'll never forget them 'till the day I die." - Dr. John
|
||||
|
||||
proposal_displayform=__1__ — __2__
|
||||
run_displayform= __2__
|
||||
crewmember_displayform=[color=__2__,__3__,__4__]__5__[/color] [color=1,1,1]__6__[/color]
|
||||
capacity_tooltip=Capacity. Sets the maximum number of crewmembers allowed.
|
||||
difficulty_tooltip=Difficulty.\n\nHigher difficulties have higher pollution and evo, higher biter damage, lower gold loot, but higher chest loot, along with small effects on the time per island, quest requirements, and silo position.\n\nDifficulty also determines the material the ship is made out of.
|
||||
mode_tooltip=Mode.
|
||||
|
||||
auto_undock_tooltip=The maximum time to stay at this location.\n\nOnce this time is reached, the boat undocks automatically. The captain can choose to leave earlier by pressing this button.
|
||||
atsea_loading_tooltip=The next destination is loading.
|
||||
leave_anytime_tooltip=The captain chooses when to undock the ship.\n\nThey can undock by pressing this button.
|
||||
resources_needed_tooltip_1=At the next destination, resources will be needed in order to undock early.\n\nFewer resources will be needed the longer you stay, eventually dropping to zero.
|
||||
resources_needed_tooltip_2=The captain can undock early by clicking this button, but only if enough resources have been stored in the captain's cabin.\n\nCost on arrival: __1__\nLeaving now will spend: __2__
|
||||
resources_needed_tooltip_3=The captain can undock by clicking this button, but only if enough resources are stored in the captain's cabin.
|
||||
resources_needed_tooltip_1_rocketvariant=At the next destination, these resources will be needed in order to undock early.\n\nFewer resources will be needed the longer you stay, eventually dropping to zero..\n\nThe silo represents a rocket launch.
|
||||
resources_needed_tooltip_2_rocketvariant=The captain can undock early by clicking this button, but only if enough resources have been stored in the captain's cabin.\n\nThe silo represents a rocket launch rather than a resource.\n\nnCost on arrival: __1__\nLeaving now will spend: __2__
|
||||
resources_needed_tooltip_3_rocketvariant=The captain can undock by clicking this button, but only if enough resources are stored in the captain's cabin.\n\nThe silo represents a rocket launch rather than a resource.
|
||||
fuel_tooltip=__1__ stored fuel.\n\nTo store more, send it to the captain's cabin. If the ship runs out of fuel, the crew loses.\n\n*Click* to open the Captain's Store, which only the captain and their officers are authorised to use.
|
@ -99,4 +99,4 @@ function Public.get(key)
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
||||
return Public
|
864
maps/pirates/ai.lua
Normal file
864
maps/pirates/ai.lua
Normal file
@ -0,0 +1,864 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
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 Math = require 'maps.pirates.math'
|
||||
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 Sea = require 'maps.pirates.surfaces.sea.sea'
|
||||
-- local Crew = require 'maps.pirates.crew'
|
||||
-- local Quest = require 'maps.pirates.quest'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local function fake_boat_target()
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.boat and memory.boat.position then
|
||||
return {valid = true, position = {x = memory.boat.position.x - 60, y = memory.boat.position.y} or nil, name = 'boatarea'}
|
||||
end
|
||||
end
|
||||
|
||||
-- fff 283 discussed pollution mechanics: https://factorio.com/blog/post/fff-283
|
||||
|
||||
local side_attack_target_names = {
|
||||
'character',
|
||||
'pumpjack',
|
||||
'radar',
|
||||
'electric-mining-drill',
|
||||
'assembling-machine-1',
|
||||
'solar-panel',
|
||||
'nuclear-reactor',
|
||||
'oil-refinery',
|
||||
'centrifuge',
|
||||
}
|
||||
|
||||
|
||||
--=== Tick Actions
|
||||
|
||||
function Public.Tick_actions(tickinterval)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if (not destination.type) or (not destination.type == Surfaces.enum.ISLAND) then return end
|
||||
if (not memory.boat.state) or (not (memory.boat.state == Boats.enum_state.LANDED or memory.boat.state == Boats.enum_state.RETREATING)) then return end
|
||||
|
||||
if (memory.game_lost) or (destination.dynamic_data.timeratlandingtime and destination.dynamic_data.timer < destination.dynamic_data.timeratlandingtime + Common.seconds_after_landing_to_enable_AI) then return end
|
||||
|
||||
if game.tick % (tickinterval * 2) == 0 and memory.boat.state == Boats.enum_state.LANDED then
|
||||
local extra_evo = 2 * tickinterval/60 * Balance.evolution_per_second()
|
||||
Common.increment_evo(extra_evo)
|
||||
destination.dynamic_data.evolution_accrued_time = destination.dynamic_data.evolution_accrued_time + extra_evo
|
||||
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.
|
||||
|
||||
|
||||
local minute_cycle = {-- even seconds only
|
||||
[2] = Public.eat_up_fraction_of_all_pollution_wrapped,
|
||||
[4] = Public.try_rogue_attack,
|
||||
[6] = Public.poke_script_groups,
|
||||
[16] = Public.try_main_attack,
|
||||
[20] = Public.poke_script_groups,
|
||||
-- [18] = Public.try_secondary_attack, --commenting out: less attacks per minute, but stronger. @TODO need to do more here
|
||||
[24] = Public.tell_biters_near_silo_to_attack_it,
|
||||
[28] = Public.eat_up_fraction_of_all_pollution_wrapped,
|
||||
[30] = Public.try_secondary_attack,
|
||||
[36] = Public.poke_script_groups,
|
||||
[46] = Public.poke_script_groups,
|
||||
[50] = Public.tell_biters_near_silo_to_attack_it,
|
||||
[52] = Public.create_mail_delivery_biters,
|
||||
[56] = Public.poke_script_groups,
|
||||
[58] = Public.poke_inactive_scripted_biters,
|
||||
}
|
||||
|
||||
if minute_cycle[(game.tick / 60) % 60] then
|
||||
minute_cycle[(game.tick / 60) % 60]()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.eat_up_fraction_of_all_pollution_wrapped()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
Public.eat_up_fraction_of_all_pollution(surface, 0.05)
|
||||
end
|
||||
|
||||
function Public.eat_up_fraction_of_all_pollution(surface, fraction_of_global_pollution)
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
-- local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
local pollution_available = memory.floating_pollution
|
||||
|
||||
local chunk_positions = {}
|
||||
for i = 1, Math.ceil(surface.map_gen_settings.width/32),1 do
|
||||
for j = 1, Math.ceil(surface.map_gen_settings.height/32),1 do
|
||||
chunk_positions[#chunk_positions + 1] = {x = 16 + i * 32 - surface.map_gen_settings.width/2, y = 16 + j * 32 - surface.map_gen_settings.height/2}
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #chunk_positions do
|
||||
local p = chunk_positions[i]
|
||||
local pollution = surface.get_pollution(p)
|
||||
local pollution_to_eat = pollution * fraction_of_global_pollution
|
||||
|
||||
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
|
||||
pollution_available = pollution_available + pollution_to_eat
|
||||
end
|
||||
end
|
||||
|
||||
-- if _DEBUG then
|
||||
-- game.print(string.format('ate %f pollution', pollution_available))
|
||||
-- end
|
||||
|
||||
memory.floating_pollution = pollution_available
|
||||
end
|
||||
|
||||
function Public.try_main_attack()
|
||||
local wave_size_multiplier = 1
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.overworldx > 0 then
|
||||
if Math.random(2) == 1 then
|
||||
-- log('attack aborted by chance')
|
||||
return nil
|
||||
end --variance in attack sizes
|
||||
if Math.random(10) == 1 then wave_size_multiplier = 1.7 end --variance in attack sizes
|
||||
if Math.random(70) == 1 then wave_size_multiplier = 3.2 end --variance in attack sizes
|
||||
if Math.random(500) == 1 then wave_size_multiplier = 5 end --variance in attack sizes
|
||||
end
|
||||
|
||||
local group = Public.spawn_group_of_scripted_biters(2/3, 6, 180, wave_size_multiplier)
|
||||
local target = Public.generate_main_attack_target()
|
||||
if not group or not group.valid or not target or not target.valid then return end
|
||||
|
||||
-- group.set_command(Public.attack_target(target))
|
||||
|
||||
Public.group_set_commands(group, Public.attack_target(target))
|
||||
|
||||
-- if _DEBUG then game.print(game.tick .. string.format(": sending main attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end
|
||||
end
|
||||
|
||||
function Public.try_secondary_attack()
|
||||
local wave_size_multiplier = 1
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.overworldx > 0 then
|
||||
if Math.random(2) == 1 then
|
||||
log('attack aborted by chance')
|
||||
end --variance in attack sizes
|
||||
if Math.random(10) == 1 then wave_size_multiplier = 1.7 end --variance in attack sizes
|
||||
if Math.random(70) == 1 then wave_size_multiplier = 3.2 end --variance in attack sizes
|
||||
if Math.random(500) == 1 then wave_size_multiplier = 5 end --variance in attack sizes
|
||||
end
|
||||
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
|
||||
|
||||
local group = Public.spawn_group_of_scripted_biters(2/3, 12, 180, wave_size_multiplier)
|
||||
if not (group and group.valid) then return end
|
||||
|
||||
local target
|
||||
if Math.random(2) == 1 then
|
||||
target = Public.generate_main_attack_target()
|
||||
else
|
||||
target = Public.generate_side_attack_target(surface, group.position)
|
||||
end
|
||||
if not group or not group.valid or not target or not target.valid then log('target invalid') return end
|
||||
|
||||
-- group.set_command(Public.attack_target(target))
|
||||
|
||||
Public.group_set_commands(group, Public.attack_target(target))
|
||||
|
||||
-- if _DEBUG then game.print(game.tick .. string.format(": sending main attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end
|
||||
end
|
||||
|
||||
function Public.try_rogue_attack()
|
||||
local wave_size_multiplier = 1
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.overworldx > 0 then
|
||||
if Math.random(2) == 1 then
|
||||
log('attack aborted by chance')
|
||||
end --variance in attack sizes
|
||||
if Math.random(10) == 1 then wave_size_multiplier = 1.7 end --variance in attack sizes
|
||||
if Math.random(70) == 1 then wave_size_multiplier = 3.2 end --variance in attack sizes
|
||||
if Math.random(500) == 1 then wave_size_multiplier = 5 end --variance in attack sizes
|
||||
end
|
||||
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
|
||||
local group = Public.spawn_group_of_scripted_biters(1/2, 6, 180, wave_size_multiplier)
|
||||
if not (group and group.valid) then return end
|
||||
local target = Public.generate_side_attack_target(surface, group.position)
|
||||
if not (target and target.valid) then return end
|
||||
|
||||
-- group.set_command(Public.attack_target(target))
|
||||
|
||||
Public.group_set_commands(group, Public.attack_target(target))
|
||||
|
||||
-- if _DEBUG then game.print(game.tick .. string.format(": sending rogue attack of %s units from {%f,%f} to %s", #group.members, group.position.x, group.position.y, target.name)) end
|
||||
end
|
||||
|
||||
|
||||
function Public.tell_biters_near_silo_to_attack_it()
|
||||
-- careful with this function, you don't want to pull biters onto the silo before any aggro has happened
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
-- don't do this too early
|
||||
if destination.dynamic_data.timer < destination.dynamic_data.timeratlandingtime + Common.seconds_after_landing_to_enable_AI * 4 then return end
|
||||
if not (destination.dynamic_data.rocketsilos and destination.dynamic_data.rocketsilos[1] and destination.dynamic_data.rocketsilos[1].valid and destination.dynamic_data.rocketsilos[1].destructible) then return end
|
||||
|
||||
local attackcommand = Public.attack_target_entity(destination.dynamic_data.rocketsilos[1])
|
||||
|
||||
if attackcommand then
|
||||
surface.set_multi_command(
|
||||
{
|
||||
command = attackcommand,
|
||||
unit_count = Math.random(1, Math.floor(1 + memory.evolution_factor * 100)),
|
||||
force = enemy_force_name,
|
||||
unit_search_distance = 10
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function Public.poke_script_groups()
|
||||
local memory = Memory.get_crew_memory()
|
||||
for index, group in pairs(memory.scripted_unit_groups) do
|
||||
local groupref = group.ref
|
||||
if not groupref.valid or groupref.surface.index ~= game.surfaces[Common.current_destination().surface_name].index or #groupref.members < 1 then
|
||||
memory.scripted_unit_groups[index] = nil
|
||||
else
|
||||
if groupref.state == defines.group_state.finished then
|
||||
if Math.random(20) == 20 then
|
||||
local command = Public.attack_obstacles(groupref.surface, {x = groupref.position.x, y = groupref.position.y})
|
||||
groupref.set_command(command)
|
||||
else
|
||||
groupref.set_autonomous() --means go home, really
|
||||
end
|
||||
elseif group.state == defines.group_state.gathering then
|
||||
groupref.start_moving()
|
||||
-- elseif group.state == defines.group_state.wander_in_group then
|
||||
-- groupref.set_autonomous() --means go home, really
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.poke_inactive_scripted_biters()
|
||||
local memory = Memory.get_crew_memory()
|
||||
for unit_number, biter in pairs(memory.scripted_biters) do
|
||||
if Public.is_biter_inactive(biter) then
|
||||
memory.scripted_biters[unit_number] = nil
|
||||
if biter.entity and biter.entity.valid then
|
||||
local target = Public.nearest_target()
|
||||
if target and target.valid then
|
||||
Public.group_set_commands(biter.entity, Public.attack_target(target))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.create_mail_delivery_biters() --these travel cross-map between bases to add a little life and spookyness
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
local spawners = surface.find_entities_filtered{name = 'biter-spawner', force = enemy_force_name}
|
||||
|
||||
local try_how_many_groups = Math.min(Math.max(0, (#spawners - 8) / 100), 4)
|
||||
|
||||
for i = 1, try_how_many_groups do
|
||||
if Math.random(2) == 1 then
|
||||
local s1 = spawners[Math.random(#spawners)]
|
||||
|
||||
local far_spawners = {}
|
||||
for j = 1, #spawners do
|
||||
local s2 = spawners[i]
|
||||
if not (i == j or Math.distance(s1.position, s2.position) < 250) then
|
||||
far_spawners[#far_spawners + 1] = s2
|
||||
end
|
||||
end
|
||||
|
||||
if #far_spawners > 0 then
|
||||
local s2 = far_spawners[Math.random(#far_spawners)]
|
||||
|
||||
memory.floating_pollution = memory.floating_pollution + 64
|
||||
local units = Public.try_spawner_spend_fraction_of_available_pollution_on_biters(s1.position, 1/4, 4, 32, 1, 'small-biter')
|
||||
memory.floating_pollution = memory.floating_pollution - 64
|
||||
|
||||
if (not units) or (not #units) or (#units == 0) then return end
|
||||
|
||||
local start_p = surface.find_non_colliding_position('rocket-silo', s1.position, 256, 2) or s1.position
|
||||
|
||||
local unit_group = surface.create_unit_group({position = start_p, force = enemy_force_name})
|
||||
for _, unit in pairs(units) do
|
||||
unit_group.add_member(unit)
|
||||
end
|
||||
memory.scripted_unit_groups[unit_group.group_number] = {ref = unit_group, script_type = 'mail-delivery'}
|
||||
|
||||
Public.group_set_commands(unit_group, {
|
||||
Public.move_to(s2.position),
|
||||
Public.wander_around(),
|
||||
})
|
||||
|
||||
-- game.print(string.format('%f biters delivering mail from %f, %f to %f, %f', #units, s1.position.x, s1.position.y, s2.position.x, s2.position.y))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--=== Spawn scripted biters
|
||||
|
||||
|
||||
function Public.spawn_group_of_scripted_biters(fraction_of_floating_pollution, minimum_avg_units, maximum_units, wave_size_multiplier)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
local spawner = Public.get_random_spawner(surface)
|
||||
if not spawner then log('no spawner found') return end
|
||||
|
||||
local nearby_units_to_bring
|
||||
if Public.get_scripted_biter_count() >= 9/10 * CoreData.total_max_biters then
|
||||
-- pick up nearby units that might be idle:
|
||||
nearby_units_to_bring = surface.find_units{area = {{spawner.position.x - 8, spawner.position.y - 8}, {spawner.position.x + 8, spawner.position.y + 8}}, force = enemy_force_name, condition = 'same'}
|
||||
else
|
||||
nearby_units_to_bring = {}
|
||||
end
|
||||
|
||||
local new_units = Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spawner.position, fraction_of_floating_pollution, minimum_avg_units, maximum_units, 1/wave_size_multiplier)
|
||||
|
||||
if (new_units and nearby_units_to_bring and (#new_units + #nearby_units_to_bring) == 0) then return end
|
||||
|
||||
local position = surface.find_non_colliding_position('rocket-silo', spawner.position, 256, 2) or spawner.position
|
||||
|
||||
local unit_group = surface.create_unit_group({position = position, force = enemy_force_name})
|
||||
for _, unit in pairs(nearby_units_to_bring) do
|
||||
unit_group.add_member(unit)
|
||||
end
|
||||
for _, unit in pairs(new_units) do
|
||||
unit_group.add_member(unit)
|
||||
end
|
||||
memory.scripted_unit_groups[unit_group.group_number] = {ref = unit_group, script_type = 'attacker'}
|
||||
return unit_group
|
||||
end
|
||||
|
||||
|
||||
function Public.try_spawner_spend_fraction_of_available_pollution_on_biters(spawnposition, fraction_of_floating_pollution, minimum_avg_units, maximum_units, unit_pollutioncost_multiplier, enforce_type)
|
||||
maximum_units = maximum_units or 256
|
||||
|
||||
-- log('ai spawning attempt params: ' .. (fraction_of_floating_pollution or '') .. ' ' .. (minimum_avg_units or '') .. ' ' .. (maximum_units or '') .. ' ' .. (unit_pollutioncost_multiplier or '') .. ' ' .. (enforce_type or ''))
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
-- local surface = spawner.surface
|
||||
-- local spawnposition = spawner.position
|
||||
-- local difficulty = memory.difficulty
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
local evolution = memory.evolution_factor
|
||||
|
||||
local units_created_count = 0
|
||||
local units_created = {}
|
||||
|
||||
local temp_floating_pollution = memory.floating_pollution
|
||||
local budget = fraction_of_floating_pollution * temp_floating_pollution
|
||||
|
||||
local initialpollution = memory.floating_pollution
|
||||
-- local initialbudget = budget
|
||||
|
||||
local base_pollution_cost_multiplier = 1
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if destination.dynamic_data and destination.dynamic_data.initial_spawner_count then
|
||||
local initial_spawner_count = destination.dynamic_data.initial_spawner_count
|
||||
|
||||
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
|
||||
-- -- destroying spawners doesn't do quite as much here:
|
||||
-- base_pollution_cost_multiplier = (initial_spawner_count/spawnerscount)^(1/3)
|
||||
-- else
|
||||
-- base_pollution_cost_multiplier = (initial_spawner_count/spawnerscount)^(1/2)
|
||||
-- end
|
||||
-- base_pollution_cost_multiplier = (initial_spawner_count/spawnerscount)^(1/2)
|
||||
-- Now directly proportional:
|
||||
base_pollution_cost_multiplier = initial_spawner_count/spawnerscount
|
||||
|
||||
if memory.overworldx == 0 then
|
||||
base_pollution_cost_multiplier = Math.max(1, base_pollution_cost_multiplier)
|
||||
end -- The first map not being fully loaded when you get there commonly means it records too few initial spawners, which this helps fix
|
||||
else
|
||||
base_pollution_cost_multiplier = 1000000
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if memory.overworldx == 0 then
|
||||
-- less biters:
|
||||
base_pollution_cost_multiplier = base_pollution_cost_multiplier * 2.30 --tuned to teach players to defend, but then to feel relaxing once they do
|
||||
end
|
||||
|
||||
base_pollution_cost_multiplier = base_pollution_cost_multiplier * unit_pollutioncost_multiplier
|
||||
|
||||
base_pollution_cost_multiplier = base_pollution_cost_multiplier * Balance.scripted_biters_pollution_cost_multiplier()
|
||||
|
||||
if destination.subtype and destination.subtype == IslandsCommon.enum.SWAMP then
|
||||
base_pollution_cost_multiplier = base_pollution_cost_multiplier * 0.9 --biters 10% more aggressive
|
||||
end
|
||||
|
||||
-- if destination.subtype and destination.subtype == IslandsCommon.enum.MAZE then
|
||||
-- base_pollution_cost_multiplier = base_pollution_cost_multiplier * 1.2 --biters 20% less aggressive
|
||||
-- end
|
||||
|
||||
if budget >= minimum_avg_units * Common.averageUnitPollutionCost(evolution) * base_pollution_cost_multiplier then
|
||||
|
||||
local function spawn(name2)
|
||||
units_created_count = units_created_count + 1
|
||||
|
||||
local unittype_pollutioncost = CoreData.biterPollutionValues[name2] * base_pollution_cost_multiplier
|
||||
|
||||
local p = surface.find_non_colliding_position(name2, spawnposition, 60, 1)
|
||||
if not p then
|
||||
p = spawnposition
|
||||
log('no position found, using spawnposition')
|
||||
end
|
||||
|
||||
local biter = surface.create_entity({name = name2, force = enemy_force_name, position = p})
|
||||
|
||||
units_created[#units_created + 1] = biter
|
||||
memory.scripted_biters[biter.unit_number] = {entity = biter, created_at = game.tick}
|
||||
|
||||
temp_floating_pollution = temp_floating_pollution - unittype_pollutioncost
|
||||
budget = budget - unittype_pollutioncost
|
||||
-- flow statistics should reflect the number of biters generated. Therefore it should mismatch the actual pollution spent, because it should miss all the factors that can vary:
|
||||
game.pollution_statistics.on_flow(name2, - CoreData.biterPollutionValues[name2] * Balance.scripted_biters_pollution_cost_multiplier())
|
||||
|
||||
return biter.unit_number
|
||||
end
|
||||
|
||||
local mixed = (Math.random(3) <= 2)
|
||||
if mixed then
|
||||
|
||||
local whilesafety = 1000
|
||||
local next_name = enforce_type or Common.get_random_unit_type(evolution)
|
||||
|
||||
while units_created_count < maximum_units and budget >= CoreData.biterPollutionValues[next_name] * base_pollution_cost_multiplier and #memory.scripted_biters < CoreData.total_max_biters and whilesafety > 0 do
|
||||
whilesafety = whilesafety - 1
|
||||
spawn(next_name)
|
||||
next_name = enforce_type or Common.get_random_unit_type(evolution)
|
||||
end
|
||||
else
|
||||
local name = enforce_type or Common.get_random_unit_type(evolution)
|
||||
|
||||
local whilesafety = 1000
|
||||
while units_created_count < maximum_units and budget >= CoreData.biterPollutionValues[name] * base_pollution_cost_multiplier and #memory.scripted_biters < CoreData.total_max_biters and whilesafety > 0 do
|
||||
whilesafety = whilesafety - 1
|
||||
spawn(name)
|
||||
end
|
||||
end
|
||||
|
||||
memory.floating_pollution = temp_floating_pollution
|
||||
end
|
||||
|
||||
if units_created_count > 0 then
|
||||
log('Spent ' .. Math.floor(100 * (initialpollution - temp_floating_pollution) / initialpollution) .. '% of ' .. Math.ceil(initialpollution) .. ' pollution budget on biters, at ' .. Math.ceil(base_pollution_cost_multiplier*100)/100 .. 'x price.')
|
||||
end
|
||||
|
||||
return units_created
|
||||
end
|
||||
|
||||
|
||||
--=== Misc Functions
|
||||
|
||||
function Public.generate_main_attack_target()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local target
|
||||
local fractioncharged = 0
|
||||
if (not destination.dynamic_data.rocketlaunched) and destination.dynamic_data.rocketsilos and destination.dynamic_data.rocketsilos[1] and destination.dynamic_data.rocketsilos[1].valid and destination.dynamic_data.rocketsilos[1].destructible and destination.dynamic_data.rocketsiloenergyconsumed and destination.dynamic_data.rocketsiloenergyneeded and destination.dynamic_data.rocketsiloenergyneeded > 0 then
|
||||
fractioncharged = destination.dynamic_data.rocketsiloenergyconsumed / destination.dynamic_data.rocketsiloenergyneeded
|
||||
end
|
||||
|
||||
local rng = Math.random()
|
||||
if rng <= fractioncharged^(1/2) then
|
||||
target = destination.dynamic_data.rocketsilos[1]
|
||||
else
|
||||
target = fake_boat_target()
|
||||
end
|
||||
return target
|
||||
end
|
||||
|
||||
function Public.generate_side_attack_target(surface, position)
|
||||
local entities = surface.find_entities_filtered{name = side_attack_target_names}
|
||||
if not entities then return end
|
||||
if Math.random(20) >= #entities then return end
|
||||
|
||||
entities = Math.shuffle(entities)
|
||||
entities = Math.shuffle_distancebiased(entities, position)
|
||||
local weights = {}
|
||||
for index, _ in pairs(entities) do
|
||||
weights[#weights + 1] = 1 + Math.floor((#entities - index) / 2)
|
||||
end
|
||||
return Math.raffle(entities, weights)
|
||||
end
|
||||
|
||||
function Public.nearest_target(surface, position)
|
||||
local names = {'rocket-silo'}
|
||||
for _, name in pairs(side_attack_target_names) do
|
||||
names[#names + 1] = name
|
||||
end
|
||||
local entities = surface.find_entities_filtered{name = names}
|
||||
local d = 9999
|
||||
local nearest = nil
|
||||
for i = 1, #entities do
|
||||
local e = entities[i]
|
||||
if e and e.valid and Math.distance(e.position, position) < d then
|
||||
nearest = e
|
||||
end
|
||||
end
|
||||
return nearest
|
||||
end
|
||||
|
||||
-- function Public.try_spend_pollution(surface, position, amount, flow_statistics_source)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
-- local force_name = memory.force_name
|
||||
|
||||
-- flow_statistics_source = flow_statistics_source or 'medium-biter'
|
||||
-- if not (position and surface and surface.valid) then return end
|
||||
|
||||
-- local pollution = surface.get_pollution(position)
|
||||
-- if pollution > amount then
|
||||
-- surface.pollute(position, -amount)
|
||||
-- game.forces[force_name].pollution_statistics.on_flow(flow_statistics_source, -amount)
|
||||
-- return true
|
||||
-- end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
function Public.get_random_spawner(surface)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local spawners = surface.find_entities_filtered({type = 'unit-spawner', force = memory.enemy_force_name})
|
||||
if (not spawners) or (not spawners[1]) then return end
|
||||
return spawners[Math.random(#spawners)]
|
||||
end
|
||||
|
||||
function Public.is_biter_inactive(biter)
|
||||
if (not biter.entity) or (not biter.entity.valid) then
|
||||
return true
|
||||
end
|
||||
if game.tick - biter.created_at > 30*60*60 then
|
||||
biter.entity.destroy()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Public.get_scripted_biter_count()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local count = 0
|
||||
for k, biter in pairs(memory.scripted_biters) do
|
||||
if biter.entity and biter.entity.valid then
|
||||
count = count + 1
|
||||
else
|
||||
memory.scripted_biters[k] = nil
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
|
||||
-----------commands-----------
|
||||
|
||||
function Public.stop()
|
||||
local command = {
|
||||
type = defines.command.stop,
|
||||
distraction = defines.distraction.none
|
||||
}
|
||||
return command
|
||||
end
|
||||
|
||||
function Public.move_to(position)
|
||||
local command = {
|
||||
type = defines.command.go_to_location,
|
||||
destination = position,
|
||||
distraction = defines.distraction.by_anything
|
||||
}
|
||||
return command
|
||||
end
|
||||
|
||||
function Public.attack_target_entity(target)
|
||||
if not target and target.valid then return end
|
||||
local command = {
|
||||
type = defines.command.attack,
|
||||
target = target,
|
||||
distraction = defines.distraction.by_anything
|
||||
}
|
||||
return command
|
||||
end
|
||||
|
||||
function Public.attack_area(position, radius)
|
||||
local command = {
|
||||
type = defines.command.attack_area,
|
||||
destination = position,
|
||||
radius = radius or 25,
|
||||
distraction = defines.distraction.by_anything
|
||||
}
|
||||
return command
|
||||
end
|
||||
|
||||
function Public.attack_obstacles(surface, position)
|
||||
local commands = {}
|
||||
local obstacles = surface.find_entities_filtered {position = position, radius = 25, type = {'simple-entity', 'tree', 'simple-entity-with-owner'}, limit = 100}
|
||||
if obstacles then
|
||||
Math.shuffle(obstacles)
|
||||
Math.shuffle_distancebiased(obstacles, position)
|
||||
for i = 1, #obstacles, 1 do
|
||||
if obstacles[i].valid then
|
||||
commands[#commands + 1] = {
|
||||
type = defines.command.attack,
|
||||
target = obstacles[i],
|
||||
distraction = defines.distraction.by_anything
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
commands[#commands + 1] = Public.move_to(position)
|
||||
local command = {
|
||||
type = defines.command.compound,
|
||||
structure_type = defines.compound_command.return_last,
|
||||
commands = commands
|
||||
}
|
||||
return command
|
||||
end
|
||||
|
||||
function Public.wander_around(ticks_to_wait) --wander individually inside group radius
|
||||
local command = {
|
||||
type = defines.command.wander,
|
||||
distraction = defines.distraction.by_anything,
|
||||
ticks_to_wait = ticks_to_wait,
|
||||
}
|
||||
return command
|
||||
end
|
||||
|
||||
function Public.group_set_commands(group, commands)
|
||||
if #commands > 0 then
|
||||
local command = {
|
||||
type = defines.command.compound,
|
||||
structure_type = defines.compound_command.return_last,
|
||||
commands = commands
|
||||
}
|
||||
group.set_command(command)
|
||||
end
|
||||
end
|
||||
|
||||
function Public.attack_target(target)
|
||||
if not target then return end
|
||||
|
||||
local commands
|
||||
if target.name == 'boatarea' then
|
||||
commands = {
|
||||
Public.attack_area(target.position, 32),
|
||||
Public.attack_area(target.position, 32),
|
||||
}
|
||||
else
|
||||
commands = {
|
||||
Public.attack_area(target.position, 8),
|
||||
Public.attack_target_entity(target),
|
||||
}
|
||||
end
|
||||
-- if Math.random(20) == 20 then
|
||||
-- commands = {
|
||||
-- Public.attack_obstacles(group.surface, {x = (group.position.x * 0.90 + target.position.x * 0.10), y = (group.position.y * 0.90 + target.position.y * 0.10)}),
|
||||
-- attackcommand,
|
||||
-- }
|
||||
-- else
|
||||
-- commands = {attackcommand}
|
||||
-- end
|
||||
return commands
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--- small group of revenge biters ---
|
||||
|
||||
|
||||
function Public.revenge_group(surface, p, target, type, bonus_evo, amount_multiplier)
|
||||
amount_multiplier = amount_multiplier or 1
|
||||
bonus_evo = bonus_evo or 0
|
||||
type = type or 'biter'
|
||||
local memory = Memory.get_crew_memory()
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
local name, count
|
||||
if type == 'biter' then
|
||||
name = Common.get_random_biter_type(memory.evolution_factor + bonus_evo)
|
||||
|
||||
if name == 'small-biter' then
|
||||
count = 5
|
||||
elseif name == 'medium-biter' then
|
||||
count = 3
|
||||
elseif name == 'big-biter' then
|
||||
count = 2
|
||||
elseif name == 'behemoth-biter' then
|
||||
count = 1
|
||||
end
|
||||
elseif type == 'spitter' then
|
||||
name = Common.get_random_spitter_type(memory.evolution_factor + bonus_evo)
|
||||
|
||||
if name == 'small-spitter' then
|
||||
count = 7
|
||||
elseif name == 'medium-spitter' then
|
||||
count = 5
|
||||
elseif name == 'big-spitter' then
|
||||
count = 3
|
||||
elseif name == 'behemoth-spitter' then
|
||||
count = 2
|
||||
end
|
||||
end
|
||||
|
||||
if (not (name and count and count>0)) then return end
|
||||
|
||||
local units = {}
|
||||
for i = 1, Math.floor(count * amount_multiplier) do
|
||||
local p2 = surface.find_non_colliding_position('wooden-chest', p, 5, 0.5)
|
||||
if p2 then
|
||||
local biter = surface.create_entity({name = name, force = enemy_force_name, position = p})
|
||||
-- local biter = surface.create_entity({name = name, force = enemy_force_name, position = p2})
|
||||
units[#units + 1] = biter
|
||||
end
|
||||
end
|
||||
|
||||
if #units > 0 then
|
||||
local unit_group = surface.create_unit_group({position = p, force = enemy_force_name})
|
||||
for _, unit in pairs(units) do
|
||||
unit_group.add_member(unit)
|
||||
end
|
||||
|
||||
if target and target.valid then
|
||||
Public.group_set_commands(unit_group, Public.attack_target(target))
|
||||
end
|
||||
unit_group.set_autonomous()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
----------- biter raiding parties -----------
|
||||
|
||||
|
||||
function Public.spawn_boat_biters(boat, max_evo, count, width)
|
||||
-- max_evolution_bonus = max_evolution_bonus or 0.3
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[boat.surface_name]
|
||||
-- local difficulty = memory.difficulty
|
||||
local enemy_force_name = boat.force_name
|
||||
-- local evolution = memory.evolution_factor
|
||||
|
||||
local p = {boat.position.x - width/2, boat.position.y}
|
||||
|
||||
local units = {}
|
||||
for i = 1, count do
|
||||
local name = Common.get_random_unit_type(max_evo - i * 0.04)
|
||||
-- local name = Common.get_random_unit_type(evolution + i/15 * max_evolution_bonus)
|
||||
-- local name = Common.get_random_unit_type(evolution + 3 * i/100)
|
||||
|
||||
local p2 = surface.find_non_colliding_position('wooden-chest', p, 8, 0.5) --needs to be wooden-chest for collisions to work properly
|
||||
if p2 then
|
||||
local biter = surface.create_entity({name = name, force = enemy_force_name, position = p2})
|
||||
|
||||
memory.scripted_biters[biter.unit_number] = {entity = biter, created_at = game.tick}
|
||||
|
||||
units[#units + 1] = biter
|
||||
end
|
||||
end
|
||||
|
||||
if #units > 0 then
|
||||
local unit_group = surface.create_unit_group({position = p, force = enemy_force_name})
|
||||
for _, unit in pairs(units) do
|
||||
unit_group.add_member(unit)
|
||||
end
|
||||
boat.unit_group = {ref = unit_group, script_type = 'landing-party'}
|
||||
end
|
||||
end
|
||||
|
||||
function Public.update_landing_party_unit_groups(boat, step_distance)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
-- move unit groups:
|
||||
local group = boat.unit_group
|
||||
local surface = game.surfaces[boat.surface_name]
|
||||
if not (group and surface and surface.valid) then return end
|
||||
|
||||
local groupref = group.ref
|
||||
if not (groupref and groupref.valid) then return end
|
||||
|
||||
local p2 = groupref.position
|
||||
if not p2 then return end
|
||||
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
local m = groupref.members
|
||||
groupref.destroy()
|
||||
|
||||
local new_group = surface.create_unit_group({position = {x = p2.x + step_distance, y = p2.y}, force = enemy_force_name})
|
||||
|
||||
boat.unit_group = {ref = new_group, script_type = 'landing-party'}
|
||||
for i = 1, #m do
|
||||
local b = m[i]
|
||||
new_group.add_member(b)
|
||||
end
|
||||
|
||||
-- if boat.spawner and boat.spawner.valid then
|
||||
-- new_group.set_command(Public.move_to(boat.spawner.position))
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- function Public.destroy_inactive_scripted_biters()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
-- local floating_pollution_accrued = 0
|
||||
-- for unit_number, biter in pairs(memory.scripted_biters) do
|
||||
-- if Public.is_biter_inactive(biter) then
|
||||
-- memory.floating_pollution = memory.floating_pollution + CoreData.biterPollutionValues[biter.entity.name]
|
||||
-- floating_pollution_accrued = floating_pollution_accrued + CoreData.biterPollutionValues[biter.entity.name]
|
||||
-- memory.scripted_biters[unit_number] = nil
|
||||
-- end
|
||||
-- end
|
||||
-- if _DEBUG and floating_pollution_accrued > 0 then game.print(game.tick .. string.format(":%f of spare pollution accrued", floating_pollution_accrued)) end
|
||||
-- end
|
||||
|
||||
--=== Data
|
||||
|
||||
|
||||
|
||||
return Public
|
614
maps/pirates/balance.lua
Normal file
614
maps/pirates/balance.lua
Normal file
@ -0,0 +1,614 @@
|
||||
|
||||
local Public = {}
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
-- this file is an API to all the balance tuning knobs
|
||||
|
||||
|
||||
Public.base_extra_character_speed = 0.20
|
||||
|
||||
Public.technology_price_multiplier = 1
|
||||
|
||||
|
||||
function Public.starting_boatEEIpower_production_MW()
|
||||
-- return 3 * Math.sloped(Common.capacity_scale(), 1/2) / 2 --/2 as we have 2
|
||||
return 3/2
|
||||
end
|
||||
function Public.starting_boatEEIelectric_buffer_size_MJ() --maybe needs to be at least the power_production
|
||||
-- return 3 * Math.sloped(Common.capacity_scale(), 1/2) / 2 --/2 as we have 2
|
||||
return 3/2
|
||||
end
|
||||
Public.EEI_stages = { --multipliers
|
||||
1,2,4,7,11
|
||||
}
|
||||
|
||||
|
||||
function Public.scripted_biters_pollution_cost_multiplier()
|
||||
return 1.3 --tuned
|
||||
end
|
||||
|
||||
function Public.cost_to_leave_multiplier()
|
||||
-- return Math.sloped(Common.difficulty(), 7/10) --should scale with difficulty similar to, but slightly slower than, passive fuel depletion rate --Edit: not sure about this?
|
||||
-- return Math.sloped(Common.difficulty(), 9/10)
|
||||
|
||||
-- extra factor now that the cost scales with time:
|
||||
return Math.sloped(Common.difficulty(), 8/10)
|
||||
end
|
||||
|
||||
Public.rocket_launch_coin_reward = 5000
|
||||
|
||||
function Public.crew_scale()
|
||||
local ret = Common.activecrewcount()/10
|
||||
if ret == 0 then ret = 1/10 end --if all players are afk
|
||||
if ret > 2.4 then ret = 2.4 end --we have to cap this because you need time to mine the ore... and big crews are a mess anyway. currently this value matches the 24 player cap
|
||||
return ret
|
||||
end
|
||||
|
||||
function Public.silo_base_est_time()
|
||||
local T = Public.expected_time_on_island() * Public.crew_scale()^(2/10) --to undo some of the time scaling
|
||||
local est_secs
|
||||
if T > 0 then
|
||||
est_secs = T/6
|
||||
else
|
||||
est_secs = 60 * 6
|
||||
end
|
||||
if Common.overworldx() == 0 then est_secs = 60 * 2 end
|
||||
return est_secs
|
||||
end
|
||||
|
||||
function Public.time_quest_seconds()
|
||||
return 2.8 * Public.silo_base_est_time()
|
||||
end
|
||||
|
||||
function Public.silo_energy_needed_MJ()
|
||||
local est_secs = Public.silo_base_est_time()
|
||||
|
||||
local est_base_power = 2*Public.starting_boatEEIpower_production_MW() * (1 + 0.05 * (Common.overworldx()/40)^(5/3))
|
||||
|
||||
return est_secs * est_base_power
|
||||
-- return est_secs * est_base_power * Math.sloped(Common.difficulty(), 1/3)
|
||||
end
|
||||
|
||||
function Public.silo_count()
|
||||
local E = Public.silo_energy_needed_MJ()
|
||||
return Math.ceil(E/(16.8 * 300)) --no more than this many seconds to charge it. Players can in fact go even faster using beacons
|
||||
-- return Math.ceil(E/(16.8 * 210)) --no more than this many seconds to charge it. Players can in fact go even faster using beacons
|
||||
end
|
||||
|
||||
|
||||
function Public.game_slowness_scale()
|
||||
-- return 1 / Public.crew_scale()^(55/100) / Math.sloped(Common.difficulty(), 1/4) --changed crew_scale factor significantly to help smaller crews
|
||||
return 1 / Public.crew_scale()^(50/100) / Math.sloped(Common.difficulty(), 1/4) --changed crew_scale factor significantly to help smaller crews
|
||||
end
|
||||
|
||||
|
||||
function Public.max_time_on_island_formula() --always >0 --tuned
|
||||
return 60 * (
|
||||
-- (32 + 2.2 * (Common.overworldx()/40)^(1/3))
|
||||
(33 + 0.2 * (Common.overworldx()/40)^(1/3)) --based on observing x=2000, lets try killing the extra time
|
||||
) * Public.game_slowness_scale()
|
||||
end
|
||||
|
||||
|
||||
function Public.max_time_on_island()
|
||||
if Common.overworldx() == 0 or ((Common.overworldx()/40) > 20) then
|
||||
-- if Common.overworldx() == 0 or ((Common.overworldx()/40) > 20 and (Common.overworldx()/40) < 25) then
|
||||
return -1
|
||||
else
|
||||
return Math.ceil(Public.max_time_on_island_formula())
|
||||
end
|
||||
end
|
||||
|
||||
Public.expected_time_fraction = 3/5
|
||||
|
||||
function Public.expected_time_on_island() --always >0
|
||||
return Public.expected_time_fraction * Public.max_time_on_island_formula()
|
||||
end
|
||||
|
||||
function Public.fuel_depletion_rate_static()
|
||||
if (not Common.overworldx()) then return 0 end
|
||||
|
||||
local T = Public.expected_time_on_island()
|
||||
|
||||
local rate
|
||||
if Common.overworldx() > 0 then
|
||||
rate = 550 * (0 + (Common.overworldx()/40)^(9/10)) * Public.crew_scale()^(1/7) * Math.sloped(Common.difficulty(), 65/100) / T --most of the crewsize dependence is through T, i.e. the coal cost per island stays the same... but the extra player dependency accounts for the fact that even in compressed time, more players seem to get more resources per island
|
||||
else
|
||||
rate = 0
|
||||
end
|
||||
|
||||
return -rate
|
||||
end
|
||||
|
||||
function Public.fuel_depletion_rate_sailing()
|
||||
if (not Common.overworldx()) then return 0 end
|
||||
|
||||
return - 7.35 * (1 + 0.135 * (Common.overworldx()/40)^(100/100)) * Math.sloped(Common.difficulty(), 1/20) --shouldn't depend on difficulty much if at all, as available resources don't depend much on difficulty
|
||||
end
|
||||
|
||||
function Public.silo_total_pollution()
|
||||
return (
|
||||
365 * (Common.difficulty()^(1.2)) * Public.crew_scale()^(2/5) * (3.2 + 0.7 * (Common.overworldx()/40)^(1.6)) --shape of the curve with x is tuned
|
||||
)
|
||||
end
|
||||
|
||||
function Public.boat_passive_pollution_per_minute(time)
|
||||
local boost = 1
|
||||
local T = Public.max_time_on_island_formula()
|
||||
if (Common.overworldx()/40) > 25 then T = T * 0.9 end
|
||||
|
||||
if time then
|
||||
if time >= 100/100 * T then --will still happen regularly, on islands without an auto-undock timer
|
||||
boost = 20
|
||||
elseif time >= 95/100 * T then
|
||||
boost = 16
|
||||
elseif time >= 90/100 * T then
|
||||
boost = 12
|
||||
elseif time >= 85/100 * T then
|
||||
boost = 8
|
||||
elseif time >= 80/100 * T then
|
||||
boost = 5
|
||||
elseif time >= 70/100 * T then
|
||||
boost = 3
|
||||
elseif time >= 60/100 * T then
|
||||
boost = 2
|
||||
elseif time >= 50/100 * T then
|
||||
boost = 1.5
|
||||
end
|
||||
end
|
||||
|
||||
return boost * (
|
||||
2.73 * Common.difficulty() * (Common.overworldx()/40)^(1.8) * (Public.crew_scale())^(55/100)
|
||||
) -- There is no _explicit_ T dependence, but it depends almost the same way on the crew_scale as T does.
|
||||
end
|
||||
|
||||
|
||||
function Public.base_evolution_leagues(leagues)
|
||||
local evo
|
||||
local overworldx = leagues
|
||||
|
||||
if overworldx == 0 then
|
||||
evo = 0
|
||||
else
|
||||
evo = (0.0201 * (overworldx/40)) * Math.sloped(Common.difficulty(), 1/5)
|
||||
|
||||
if overworldx > 600 and overworldx < 1000 then
|
||||
evo = evo + (0.0025 * (overworldx - 600)/40)
|
||||
elseif overworldx > 1000 then
|
||||
evo = evo + 0.0025 * 10
|
||||
end --extra slope from 600 to 1000 adds 2.5% evo
|
||||
end
|
||||
|
||||
return evo
|
||||
end
|
||||
|
||||
function Public.expected_time_evo()
|
||||
return 0.14
|
||||
end
|
||||
|
||||
function Public.evolution_per_second()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
local T = Public.expected_time_on_island() --always greater than 0
|
||||
local rate = Public.expected_time_evo() / T
|
||||
if Common.overworldx() == 0 then rate = 0 end
|
||||
|
||||
-- scale by biter nests remaining:
|
||||
if destination and destination.dynamic_data then
|
||||
local initial_spawner_count = destination.dynamic_data.initial_spawner_count
|
||||
if initial_spawner_count and initial_spawner_count > 0 then
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if surface and surface.valid then
|
||||
rate = rate * Common.spawner_count(surface) / destination.dynamic_data.initial_spawner_count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- if _DEBUG then
|
||||
-- local surface = game.surfaces[destination.surface_name]
|
||||
-- game.print(Common.spawner_count(surface) .. ' ' .. destination.dynamic_data.initial_spawner_count)
|
||||
-- end
|
||||
|
||||
return rate
|
||||
end
|
||||
|
||||
function Public.evolution_per_nest_kill() --it's important to have evo go up with biter base kills, to provide resistance if you try to plow through all the bases
|
||||
local destination = Common.current_destination()
|
||||
if Common.overworldx() == 0 then return 0 end
|
||||
|
||||
if destination and destination.dynamic_data and destination.dynamic_data.timer and destination.dynamic_data.timer > 0 and destination.dynamic_data.initial_spawner_count and destination.dynamic_data.initial_spawner_count > 0 then
|
||||
|
||||
local initial_spawner_count = destination.dynamic_data.initial_spawner_count
|
||||
local time = destination.dynamic_data.timer
|
||||
-- local time_to_jump_to = Public.expected_time_on_island() * ((1/Public.expected_time_fraction)^(2/3))
|
||||
local time_to_jump_to = Public.max_time_on_island_formula()
|
||||
if time > time_to_jump_to then return 0
|
||||
else
|
||||
-- evo it 'would have' contributed:
|
||||
return (1/initial_spawner_count) * Public.expected_time_evo() * (time_to_jump_to - time)/time_to_jump_to
|
||||
end
|
||||
else
|
||||
return 0
|
||||
end
|
||||
|
||||
-- return 0.003 * Common.difficulty()
|
||||
end
|
||||
|
||||
function Public.evolution_per_full_silo_charge()
|
||||
--too low and you always charge immediately, too high and you always charge late
|
||||
-- return 0.05
|
||||
-- observed x=2000 run, changed this to:
|
||||
return 0.05 + 0.03 * Common.overworldx()/1000
|
||||
end
|
||||
|
||||
function Public.bonus_damage_to_humans()
|
||||
local ret = 0.025
|
||||
local diff = Common.difficulty()
|
||||
if diff <= 0.7 then ret = 0 end
|
||||
if diff >= 1.3 then ret = 0.050 end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.periodic_free_resources_per_x()
|
||||
return {
|
||||
}
|
||||
-- return {
|
||||
-- {name = 'iron-plate', count = Math.ceil(5 * (Common.overworldx()/40)^(2/3))},
|
||||
-- {name = 'copper-plate', count = Math.ceil(1 * (Common.overworldx()/40)^(2/3))},
|
||||
-- }
|
||||
end
|
||||
|
||||
function Public.periodic_free_resources_per_destination_5_seconds()
|
||||
return {
|
||||
}
|
||||
-- return {
|
||||
-- {name = 'iron-ore', count = Math.ceil(7 * (Common.overworldx()/40)^(0.6))},
|
||||
-- {name = 'copper-ore', count = Math.ceil(3 * (Common.overworldx()/40)^(0.6))},
|
||||
-- }
|
||||
end
|
||||
|
||||
function Public.class_resource_scale()
|
||||
return 1 / (Public.crew_scale()^(2/5)) --already helped by longer timescales
|
||||
end
|
||||
|
||||
function Public.biter_base_density_scale()
|
||||
local p = Public.crew_scale()
|
||||
if p >= 1 then
|
||||
return p^(1/2)
|
||||
else
|
||||
return Math.max((p*10/6)^(1/2), 0.6)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.launch_fuel_reward()
|
||||
return Math.ceil(1000 * (1 + 0.13 * (Common.overworldx()/40)^(9/10)))
|
||||
-- return Math.ceil(1000 * (1 + 0.1 * (Common.overworldx()/40)^(8/10)) / Math.sloped(Common.difficulty(), 1/4))
|
||||
end
|
||||
|
||||
function Public.quest_reward_multiplier()
|
||||
return (0.4 + 0.08 * (Common.overworldx()/40)^(8/10)) * Math.sloped(Common.difficulty(), 1/3) * (Public.crew_scale())^(1/8)
|
||||
end
|
||||
|
||||
function Public.island_richness_avg_multiplier()
|
||||
local ret
|
||||
-- local base = 0.7 + 0.1 * (Common.overworldx()/40)^(7/10) --tuned tbh
|
||||
local base = 0.73 + 0.110 * (Common.overworldx()/40)^(7/10) --tuned tbh
|
||||
|
||||
ret = base * Math.sloped(Public.crew_scale(), 1/40) --we don't really have resources scaling by player count in this resource-constrained scenario, but we scale a little, to accommodate each player filling their inventory with useful tools. also, I would do higher than 1/40, but we go even slightly lower because we're applying this somewhat sooner than players actually get there.
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function Public.resource_quest_multiplier()
|
||||
return (1.0 + 0.075 * (Common.overworldx()/40)^(8/10)) * Math.sloped(Common.difficulty(), 1/3) * (Public.crew_scale())^(1/8)
|
||||
end
|
||||
|
||||
|
||||
function Public.apply_crew_buffs_per_x(force)
|
||||
force.laboratory_productivity_bonus = Math.max(0, 7/100 * (Common.overworldx()/40) - (10*(Common.difficulty()) - 5)) --difficulty causes lab productivity boosts to start later
|
||||
end
|
||||
|
||||
function Public.class_cost()
|
||||
return 8000
|
||||
-- return Math.ceil(10000 / (Public.crew_scale()*10/4)^(1/6))
|
||||
end
|
||||
|
||||
|
||||
Public.covered_first_appears_at = 40
|
||||
|
||||
Public.starting_fuel = 4000
|
||||
|
||||
Public.silo_max_hp = 8000
|
||||
|
||||
function Public.pistol_damage_multiplier() return 2.25 end --2.0 slightly too low, 2.5 causes players to yell at each other for not using pistol
|
||||
|
||||
Public.kraken_spawns_base_extra_evo = 0.35
|
||||
|
||||
function Public.kraken_evo_increase_per_shot()
|
||||
return 1/100 * 0.07
|
||||
end
|
||||
|
||||
function Public.sandworm_evo_increase_per_spawn()
|
||||
if _DEBUG then
|
||||
return 1/100
|
||||
else
|
||||
return 1/100 * 1/8 * Math.sloped(Common.difficulty(), 3/5)
|
||||
end
|
||||
end
|
||||
|
||||
function Public.kraken_kill_reward()
|
||||
return {{name = 'sulfuric-acid-barrel', count = 10}}
|
||||
end
|
||||
|
||||
function Public.kraken_health()
|
||||
return Math.ceil(3500 * Math.max(1, 1 + 0.08 * ((Common.overworldx()/40)^(13/10)-6)) * (Public.crew_scale()^(5/8)) * Math.sloped(Common.difficulty(), 3/4))
|
||||
end
|
||||
|
||||
Public.kraken_regen_scale = 0.1 --starting off low
|
||||
|
||||
function Public.krakens_per_slot()
|
||||
local rng = Math.random()
|
||||
if rng < 0.03 then
|
||||
return 2
|
||||
elseif rng < 0.25 then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function Public.krakens_per_free_slot(overworldx)
|
||||
local rng = Math.random()
|
||||
local multiplier = 1
|
||||
if overworldx and overworldx > 600 then
|
||||
multiplier = 1 + (overworldx-600)/600
|
||||
end
|
||||
if rng < 0.0025 * multiplier then
|
||||
return 3
|
||||
elseif rng < 0.075 * multiplier then
|
||||
return 1
|
||||
elseif rng < 0.5 * multiplier then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.main_shop_cost_multiplier()
|
||||
return 1
|
||||
end
|
||||
|
||||
function Public.barter_decay_parameter()
|
||||
return 0.95
|
||||
end
|
||||
|
||||
function Public.sandworm_speed()
|
||||
return 6.4 * Math.sloped(Common.difficulty(), 1/5)
|
||||
end
|
||||
|
||||
-- function Public.island_otherresources_prospect_decay_parameter()
|
||||
-- return 0.95
|
||||
-- end
|
||||
|
||||
Public.research_buffs = { --currently disabled anyway
|
||||
-- these already give .1 productivity so we're adding .1 to get to 20%
|
||||
['mining-productivity-1'] = {['mining-drill-productivity-bonus'] = .1},
|
||||
['mining-productivity-2'] = {['mining-drill-productivity-bonus'] = .1},
|
||||
['mining-productivity-3'] = {['mining-drill-productivity-bonus'] = .1},
|
||||
['mining-productivity-4'] = {['mining-drill-productivity-bonus'] = .1},
|
||||
-- -- these already give .1 productivity so we're adding .1 to get to 20%
|
||||
-- ['mining-productivity-1'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
||||
-- ['mining-productivity-2'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
||||
-- ['mining-productivity-3'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
||||
-- ['mining-productivity-4'] = {['mining-drill-productivity-bonus'] = .1, ['character-inventory-slots-bonus'] = 5},
|
||||
}
|
||||
|
||||
|
||||
function Public.flamers_tech_multipliers()
|
||||
return 0.8
|
||||
end
|
||||
|
||||
function Public.flamers_base_nerf()
|
||||
return -0.2
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.player_ammo_damage_modifiers() -- modifiers are fractional. bullet affects gun turrets, but flamethrower does not affect flamer turrets
|
||||
local data = {
|
||||
['artillery-shell'] = 0,
|
||||
['biological'] = 0,
|
||||
['bullet'] = 0.1,
|
||||
['cannon-shell'] = 0,
|
||||
['capsule'] = 0,
|
||||
['electric'] = 0,
|
||||
['flamethrower'] = 0, --these nerfs are elsewhere for finer control
|
||||
['grenade'] = -0.05,
|
||||
['landmine'] = 0,
|
||||
['melee'] = 0, -- doesn't do anything apparently
|
||||
['rocket'] = 0,
|
||||
['shotgun-shell'] = 0
|
||||
}
|
||||
return data
|
||||
end
|
||||
function Public.player_turret_attack_modifiers()
|
||||
local data = {
|
||||
['gun-turret'] = 0,
|
||||
['artillery-turret'] = 0,
|
||||
['laser-turret'] = 0,
|
||||
}
|
||||
return data
|
||||
end
|
||||
function Public.player_gun_speed_modifiers()
|
||||
local data = {
|
||||
['artillery-shell'] = 0,
|
||||
['biological'] = 0,
|
||||
['bullet'] = 0,
|
||||
['cannon-shell'] = 0,
|
||||
['capsule'] = 0,
|
||||
['electric'] = 0,
|
||||
['flamethrower'] = 0, --these nerfs are elsewhere for finer control
|
||||
['grenade'] = -0.25,
|
||||
['landmine'] = 0,
|
||||
['melee'] = 0, -- doesn't do anything apparently
|
||||
['rocket'] = 0,
|
||||
['shotgun-shell'] = 0
|
||||
}
|
||||
return data
|
||||
end
|
||||
|
||||
|
||||
Public.starting_items_player = {['pistol'] = 1, ['firearm-magazine'] = 12, ['raw-fish'] = 1, ['iron-plate'] = 12, ['medium-electric-pole'] = 4}
|
||||
|
||||
Public.starting_items_player_late = {['pistol'] = 1, ['firearm-magazine'] = 5}
|
||||
|
||||
function Public.starting_items_crew_upstairs()
|
||||
return {
|
||||
{['steel-plate'] = 38},
|
||||
{['stone-brick'] = 60},
|
||||
{['grenade'] = 3},
|
||||
{['shotgun'] = 2, ['shotgun-shell'] = 36},
|
||||
-- {['raw-fish'] = 5},
|
||||
{['coin'] = 1000},
|
||||
}
|
||||
end
|
||||
|
||||
function Public.starting_items_crew_downstairs()
|
||||
return {
|
||||
{['transport-belt'] = Math.random(600,650)},
|
||||
{['underground-belt'] = 80},
|
||||
{['splitter'] = Math.random(50,56)},
|
||||
{['inserter'] = Math.random(120,140)},
|
||||
{['storage-tank'] = 4},
|
||||
{['medium-electric-pole'] = Math.random(15,21)},
|
||||
{['coin'] = 2000},
|
||||
{['solar-panel'] = 3},
|
||||
{['accumulator'] = 1},
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.covered_entry_price_scale()
|
||||
return 0.85 * (1 + 0.033 * (Common.overworldx()/40 - 1)) * ((1 + Public.crew_scale())^(1/3)) * Math.sloped(Common.difficulty(), 1/2) --whilst resource scales tend to be held fixed with crew size, we account slightly for the fact that more players tend to handcraft more
|
||||
end
|
||||
|
||||
-- if the prices are too high, players will accidentally throw too much in when they can't do it
|
||||
|
||||
Public.covered1_entry_price_data_raw = { --watch out that the raw_materials chest can only hold e.g. 4.8 iron-plates
|
||||
-- choose things that are easy to make at outposts
|
||||
{1, 0, 1, false, {
|
||||
price = {name = 'iron-stick', count = 1500},
|
||||
raw_materials = {{name = 'iron-plate', count = 750}}}, {}},
|
||||
{0.85, 0, 1, false, {
|
||||
price = {name = 'copper-cable', count = 1500},
|
||||
raw_materials = {{name = 'copper-plate', count = 750}}}, {}},
|
||||
|
||||
{1, 0, 0.3, false, {
|
||||
price = {name = 'small-electric-pole', count = 450},
|
||||
raw_materials = {{name = 'copper-plate', count = 900}}}, {}},
|
||||
{1, 0.1, 1, false, {
|
||||
price = {name = 'assembling-machine-1', count = 80},
|
||||
raw_materials = {{name = 'iron-plate', count = 1760}, {name = 'copper-plate', count = 360}}}, {}},
|
||||
{1, 0, 0.15, false, {
|
||||
price = {name = 'burner-mining-drill', count = 150},
|
||||
raw_materials = {{name = 'iron-plate', count = 1350}}}, {}},
|
||||
{0.75, 0, 0.6, false, {
|
||||
price = {name = 'burner-inserter', count = 300},
|
||||
raw_materials = {{name = 'iron-plate', count = 900}}}, {}},
|
||||
{1, 0.05, 0.7, false, {
|
||||
price = {name = 'small-lamp', count = 300},
|
||||
raw_materials = {{name = 'iron-plate', count = 600}, {name = 'copper-plate', count = 900}}}, {}},
|
||||
{1, 0, 1, false, {
|
||||
price = {name = 'firearm-magazine', count = 700},
|
||||
raw_materials = {{name = 'iron-plate', count = 2800}}}, {}},
|
||||
{1, 0, 1, false, {
|
||||
price = {name = 'constant-combinator', count = 276},
|
||||
raw_materials = {{name = 'iron-plate', count = 552}, {name = 'copper-plate', count = 1518}}}, {}},
|
||||
|
||||
{1, 0.05, 1, false, {
|
||||
price = {name = 'stone-furnace', count = 250},
|
||||
raw_materials = {}}, {}},
|
||||
{1, 0.4, 1.6, true, {
|
||||
price = {name = 'advanced-circuit', count = 180},
|
||||
raw_materials = {{name = 'iron-plate', count = 360}, {name = 'copper-plate', count = 900}, {name = 'plastic-bar', count = 360}}}, {}},
|
||||
|
||||
{0.5, -0.5, 0.5, true, {
|
||||
price = {name = 'wooden-chest', count = 400},
|
||||
raw_materials = {}}, {}},
|
||||
{0.5, 0, 1, true, {
|
||||
price = {name = 'iron-chest', count = 250},
|
||||
raw_materials = {{name = 'iron-plate', count = 2000}}}, {}},
|
||||
{0.5, 0.25, 1.75, true, {
|
||||
price = {name = 'steel-chest', count = 125},
|
||||
raw_materials = {{name = 'steel-plate', count = 1000}}}, {}},
|
||||
}
|
||||
|
||||
function Public.covered1_entry_price_data()
|
||||
local ret = {}
|
||||
local data = Public.covered1_entry_price_data_raw
|
||||
for i = 1, #data do
|
||||
local data_item = data[i]
|
||||
ret[#ret + 1] = {
|
||||
weight = data_item[1],
|
||||
game_completion_progress_min = data_item[2],
|
||||
game_completion_progress_max = data_item[3],
|
||||
scaling = data_item[4],
|
||||
item = data_item[5],
|
||||
map_subtypes = data_item[6],
|
||||
}
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.covered1_entry_price()
|
||||
-- local rng = Math.random()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
-- local overworldx = memory.overworldx or 0
|
||||
|
||||
local game_completion_progress = Math.max(Math.min(Math.sloped(Common.difficulty(),1/2) * Common.game_completion_progress(), 1), 0)
|
||||
|
||||
local data = Public.covered1_entry_price_data()
|
||||
local types, weights = {}, {}
|
||||
for i = 1, #data, 1 do
|
||||
table.insert(types, data[i].item)
|
||||
|
||||
local destination = Common.current_destination()
|
||||
if not (data[i].map_subtypes and #data[i].map_subtypes > 0 and destination and destination.subtype and data[i].map_subtypes and (not Utils.contains(data[i].map_subtypes, destination.subtype))) then
|
||||
if data[i].scaling then -- scale down weights away from the midpoint 'peak' (without changing the mean)
|
||||
local midpoint = (data[i].game_completion_progress_max + data[i].game_completion_progress_min) / 2
|
||||
local difference = (data[i].game_completion_progress_max - data[i].game_completion_progress_min)
|
||||
table.insert(weights, data[i].weight * Math.max(0, 1 - (Math.abs(game_completion_progress - midpoint) / (difference / 2))))
|
||||
else -- no scaling
|
||||
if data[i].game_completion_progress_min <= game_completion_progress and data[i].game_completion_progress_max >= game_completion_progress then
|
||||
table.insert(weights, data[i].weight)
|
||||
else
|
||||
table.insert(weights, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local res = Utils.deepcopy(Math.raffle(types, weights))
|
||||
|
||||
res.price.count = Math.ceil(res.price.count * Public.covered_entry_price_scale())
|
||||
|
||||
for i, _ in pairs(res.raw_materials) do
|
||||
res.raw_materials[i].count = Math.ceil(res.raw_materials[i].count * Public.covered_entry_price_scale() * (0.9 + 0.2 * Math.random()))
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
return Public
|
66
maps/pirates/boat_upgrades.lua
Normal file
66
maps/pirates/boat_upgrades.lua
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Loot = require 'maps.pirates.loot'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
-- local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local Hold = require 'maps.pirates.surfaces.hold'
|
||||
|
||||
local Public = {}
|
||||
|
||||
-- September 2021: Reworking the game so that you start on a 'sloop with hold', but can customize the ship with upgrades.
|
||||
|
||||
-- I'm thinking these can start by simply being shop icons.
|
||||
|
||||
-- In the hold, we can extend the hold size by placing tiles. Perhaps the space that is extended could be random, as usual to dissuade repetitive builds.
|
||||
|
||||
-- For the deck, we don't really want to do that. It's probably safest to stick to things like upgrading the accumulator.
|
||||
|
||||
local enum = {
|
||||
EXTRA_HOLD = 'extra_hold',
|
||||
MORE_POWER = 'upgrade_power',
|
||||
UNLOCK_MERCHANTS = 'unlock_merchants',
|
||||
ROCKETS_FOR_SALE = 'rockets_for_sale',
|
||||
}
|
||||
Public.enum = enum
|
||||
Public.List = {
|
||||
enum.EXTRA_HOLD,
|
||||
enum.MORE_POWER,
|
||||
enum.UNLOCK_MERCHANTS,
|
||||
enum.ROCKETS_FOR_SALE,
|
||||
}
|
||||
|
||||
Public.crowsnest_display_form = {
|
||||
[enum.EXTRA_HOLD] = 'Extra Hold',
|
||||
[enum.MORE_POWER] = 'Power',
|
||||
[enum.UNLOCK_MERCHANTS] = 'Unlock Merchants',
|
||||
[enum.ROCKETS_FOR_SALE] = 'Unlock Rockets',
|
||||
}
|
||||
|
||||
function Public.execute_upgade(upgrade_type)
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
if upgrade_type == enum.EXTRA_HOLD then
|
||||
Hold.add_another_hold_surface()
|
||||
elseif upgrade_type == enum.MORE_POWER then
|
||||
boat.EEI_stage = boat.EEI_stage + 1
|
||||
Boats.update_EEIs(boat)
|
||||
elseif upgrade_type == enum.UNLOCK_MERCHANTS then
|
||||
memory.merchant_ships_unlocked = true
|
||||
elseif upgrade_type == enum.ROCKETS_FOR_SALE then
|
||||
memory.rockets_for_sale = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
return Public
|
969
maps/pirates/commands.lua
Normal file
969
maps/pirates/commands.lua
Normal file
@ -0,0 +1,969 @@
|
||||
--luacheck: ignore
|
||||
--luacheck ignores because mass requires is a code templating choice...
|
||||
|
||||
local Color = require 'utils.color_presets'
|
||||
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 Interface = require 'maps.pirates.interface'
|
||||
local Upgrades = require 'maps.pirates.boat_upgrades'
|
||||
local Effects = require 'maps.pirates.effects'
|
||||
local Kraken = require 'maps.pirates.surfaces.sea.kraken'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local simplex_noise = require 'utils.simplex_noise'.d2
|
||||
local Token = require 'utils.token'
|
||||
local Task = require 'utils.task'
|
||||
local Highscore = require 'maps.pirates.highscore'
|
||||
local CustomEvents = require 'maps.pirates.custom_events'
|
||||
local Classes = require 'maps.pirates.roles.classes'
|
||||
|
||||
local GUIcolor = require 'maps.pirates.gui.color'
|
||||
|
||||
commands.add_command(
|
||||
'ok',
|
||||
'is used to accept captainhood.',
|
||||
function(cmd)
|
||||
local player = game.players[cmd.player_index]
|
||||
if not Common.validate_player(player) then return end
|
||||
local crew_id = tonumber(string.sub(game.players[cmd.player_index].force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Roles.player_confirm_captainhood(player)
|
||||
end)
|
||||
|
||||
-- Disabled for information-flow reasons:
|
||||
-- commands.add_command(
|
||||
-- 'classes',
|
||||
-- 'Prints the available classes in the game.',
|
||||
-- function(cmd)
|
||||
-- local player = game.players[cmd.player_index]
|
||||
-- if not Common.validate_player(player) then return end
|
||||
-- player.print('[color=gray]' .. Roles.get_classes_print_string() .. '[/color]')
|
||||
-- end)
|
||||
|
||||
commands.add_command(
|
||||
'classinfo',
|
||||
'{classname} returns the definition of the named class.',
|
||||
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)
|
||||
if string then
|
||||
Common.notify_player_expected(player, 'Class definition for ' .. string)
|
||||
else
|
||||
Common.notify_player_error(player, 'Command error: Class \'' .. param .. '\' not found.')
|
||||
end
|
||||
else
|
||||
Common.notify_player_expected(player, '/classinfo {classname} returns the definition of the named class.')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'take',
|
||||
'{classname} takes a spare class with the given name for yourself.',
|
||||
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
|
||||
for _, class in ipairs(Classes.Class_List) do
|
||||
if Classes.display_form[class]:lower() == param:lower() then
|
||||
Classes.assign_class(player.index, class, true)
|
||||
return true
|
||||
end
|
||||
end
|
||||
--fallthrough:
|
||||
Common.notify_player_error(player, 'Command error: Class \'' .. param .. '\' not found.')
|
||||
return false
|
||||
else
|
||||
Common.notify_player_expected(player, '/take {classname} takes a spare class with the given name for yourself.')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'giveup',
|
||||
'gives up your current class, making it available for others.',
|
||||
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
|
||||
Classes.try_renounce_class(player, true)
|
||||
else
|
||||
Common.notify_player_error(player, 'Command error: parameter not needed.')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'ccolor',
|
||||
'is an extension to the built-in /color command, with more colors.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
local player_index = cmd.player_index
|
||||
if player_index then
|
||||
local player = game.players[player_index]
|
||||
if player and player.valid then
|
||||
if cmd.parameter then
|
||||
if PlayerColors.colors[param] then
|
||||
local rgb = PlayerColors.colors[param]
|
||||
player.color = rgb
|
||||
player.chat_color = rgb
|
||||
local message = '[color=' .. rgb.r .. ',' .. rgb.g .. ',' .. rgb.b .. ']' .. player.name .. ' chose the color ' .. param .. '[/color] (via /ccolor).'
|
||||
Common.notify_game(message)
|
||||
else
|
||||
Common.notify_player_error(player, 'Command error: Color \'' .. param .. '\' not found.')
|
||||
end
|
||||
else
|
||||
local color = PlayerColors.bright_color_names[Math.random(#PlayerColors.bright_color_names)]
|
||||
local rgb = PlayerColors.colors[color]
|
||||
if not rgb then return end
|
||||
player.color = rgb
|
||||
player.chat_color = rgb
|
||||
local message = '[color=' .. rgb.r .. ',' .. rgb.g .. ',' .. rgb.b .. ']' .. player.name .. '\'s color randomized to ' .. color .. '[/color] (via /ccolor).' --'randomly became' was amusing, but let's not
|
||||
Common.notify_game(message)
|
||||
-- disabled due to lag:
|
||||
-- GUIcolor.toggle_window(player)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
|
||||
local go_2 = Token.register(
|
||||
function(data)
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
memory.mapbeingloadeddestination_index = 1
|
||||
memory.loadingticks = 0
|
||||
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
-- surface.request_to_generate_chunks({x = 0, y = 0}, 10)
|
||||
-- surface.force_generate_chunk_requests()
|
||||
Progression.go_from_starting_dock_to_first_destination()
|
||||
end
|
||||
)
|
||||
local go_1 = Token.register(
|
||||
function(data)
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Overworld.ensure_lane_generated_up_to(0, Crowsnest.Data.visibilitywidth/2)
|
||||
Overworld.ensure_lane_generated_up_to(24, Crowsnest.Data.visibilitywidth/2)
|
||||
Overworld.ensure_lane_generated_up_to(-24, Crowsnest.Data.visibilitywidth/2)
|
||||
memory.currentdestination_index = 1
|
||||
script.raise_event(CustomEvents.enum['update_crew_progress_gui'], {})
|
||||
Surfaces.create_surface(Common.current_destination())
|
||||
Task.set_timeout_in_ticks(60, go_2, {})
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
local function check_admin(cmd)
|
||||
local Session = require 'utils.datastore.session_data'
|
||||
local player = game.players[cmd.player_index]
|
||||
local trusted = Session.get_trusted_table()
|
||||
local p
|
||||
if player then
|
||||
if player ~= nil then
|
||||
p = player.print
|
||||
if not player.admin then
|
||||
p('[ERROR] Only admins are allowed to run this command!', Color.fail)
|
||||
return false
|
||||
end
|
||||
else
|
||||
p = log
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function check_captain(cmd)
|
||||
local player = game.players[cmd.player_index]
|
||||
local p
|
||||
if player then
|
||||
if player ~= nil then
|
||||
p = player.print
|
||||
if not Common.validate_player(player) then return end
|
||||
local crew_id = tonumber(string.sub(game.players[cmd.player_index].force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if not (Roles.player_privilege_level(player) >= Roles.privilege_levels.CAPTAIN) then
|
||||
p('[ERROR] Only captains are allowed to run this command!', Color.fail)
|
||||
return false
|
||||
end
|
||||
else
|
||||
p = log
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function check_captain_or_admin(cmd)
|
||||
local player = game.players[cmd.player_index]
|
||||
local p
|
||||
if player then
|
||||
if player ~= nil then
|
||||
p = player.print
|
||||
if not Common.validate_player(player) then return end
|
||||
local crew_id = tonumber(string.sub(game.players[cmd.player_index].force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if not (player.admin or Roles.player_privilege_level(player) >= Roles.privilege_levels.CAPTAIN) then
|
||||
p('[ERROR] Only captains are allowed to run this command!', Color.fail)
|
||||
return false
|
||||
end
|
||||
else
|
||||
p = log
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
local function check_trusted(cmd)
|
||||
local Session = require 'utils.datastore.session_data'
|
||||
local player = game.players[cmd.player_index]
|
||||
local trusted = Session.get_trusted_table()
|
||||
local p
|
||||
if player then
|
||||
if player ~= nil then
|
||||
p = player.print
|
||||
if not (trusted[player.name] or player.admin) then
|
||||
p('[ERROR] Only admins and trusted weebs are allowed to run this command!', Color.fail)
|
||||
return false
|
||||
end
|
||||
else
|
||||
p = log
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
commands.add_command(
|
||||
'set_max_crews',
|
||||
'is an admin command to set the maximum number of concurrent crews allowed on the server.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local global_memory = Memory.get_global_memory()
|
||||
|
||||
if tonumber(param) then
|
||||
global_memory.active_crews_cap = tonumber(param)
|
||||
Common.notify_player_expected(player, 'The maximum number of concurrent crews has been set to ' .. param .. '.')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
commands.add_command(
|
||||
'plank',
|
||||
'is a captain command to remove a player by making them a spectator.',
|
||||
function(cmd)
|
||||
local player = game.players[cmd.player_index]
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_captain_or_admin(cmd) then
|
||||
if param and game.players[param] and game.players[param].index then
|
||||
Crew.plank(player, game.players[param])
|
||||
else
|
||||
Common.notify_player_error(player, 'Command error: Invalid player name.')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'officer',
|
||||
'is a captain command to make a player into an officer, or remove them as one.',
|
||||
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
|
||||
Roles.unmake_officer(player, game.players[param])
|
||||
else
|
||||
Roles.make_officer(player, game.players[param])
|
||||
end
|
||||
else
|
||||
Common.notify_player_error(player, 'Command error: Invalid player name.')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'undock',
|
||||
'is a captain command to undock the ship.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_captain_or_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.boat.state == Boats.enum_state.DOCKED then
|
||||
Progression.undock_from_dock(true)
|
||||
elseif memory.boat.state == Boats.enum_state.LANDED then
|
||||
Progression.try_retreat_from_island(player, true)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'req',
|
||||
'is a captain command to take \'important\' items from the crew into your inventory.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_captain(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local memory = Memory.get_crew_memory()
|
||||
Roles.captain_requisition(memory.playerindex_captain)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'dump_highscores',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
if not Common.validate_player(player) then return end
|
||||
local crew_id = tonumber(string.sub(game.players[cmd.player_index].force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Highscore.dump_highscores()
|
||||
player.print('Highscores dumped.')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'setcaptain',
|
||||
'{player} is an admin command to set the crew\'s captain to {player}.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if param and game.players[param] and game.players[param].index then
|
||||
Roles.make_captain(game.players[param])
|
||||
else
|
||||
Common.notify_player_error(player, 'Command error: Invalid player name.')
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'summoncrew',
|
||||
'is an admin command to summon the crew to the ship.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
Crew.summon_crew()
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'setclass',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
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] = tonumber(param)
|
||||
player.print('Set own class to ' .. param .. '.')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'setevo',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
Common.set_evo(tonumber(param))
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'modi',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
local entities = surface.find_entities_filtered{position = player.position, radius = 500}
|
||||
for _, e in pairs(entities) do
|
||||
if e and e.valid then
|
||||
-- e.force = memory.force
|
||||
e.minable = true
|
||||
e.destructible = true
|
||||
e.rotatable = true
|
||||
end
|
||||
end
|
||||
player.print('nearby entities made modifiable')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'ret',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
Progression.retreat_from_island(true)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'jump',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
Overworld.try_overworld_move_v2({x = 40, y = 0})
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'advu',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
Overworld.try_overworld_move_v2{x = 0, y = -24}
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'advd',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
Overworld.try_overworld_move_v2{x = 0, y = 24}
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
commands.add_command(
|
||||
'overwrite_scores_specific',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
if not Common.validate_player(player) then return end
|
||||
local crew_id = tonumber(string.sub(game.players[cmd.player_index].force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if Highscore.overwrite_scores_specific() then player.print('Highscores overwritten.') end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
if _DEBUG then
|
||||
|
||||
commands.add_command(
|
||||
'go',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
|
||||
local proposal = {
|
||||
capacity_option = 3,
|
||||
difficulty_option = 2,
|
||||
-- mode_option = 'left',
|
||||
endorserindices = { 1 },
|
||||
name = "AdminRun"
|
||||
}
|
||||
|
||||
Memory.set_working_id(1)
|
||||
|
||||
Crew.initialise_crew(proposal)
|
||||
Crew.initialise_crowsnest() --contains a Task
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = Utils.deepcopy(Surfaces.Lobby.StartingBoats[memory.id])
|
||||
|
||||
for _, p in pairs(game.connected_players) do
|
||||
p.teleport({x = -30, y = boat.position.y}, game.surfaces[boat.surface_name])
|
||||
end
|
||||
|
||||
Progression.set_off_from_starting_dock()
|
||||
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
-- local boat = Utils.deepcopy(Surfaces.Lobby.StartingBoats[memory.id])
|
||||
-- memory.boat = boat
|
||||
-- boat.dockedposition = boat.position
|
||||
-- boat.decksteeringchests = {}
|
||||
-- boat.crowsneststeeringchests = {}
|
||||
|
||||
Task.set_timeout_in_ticks(120, go_1, {})
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'chnk',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
for i = 0, 13 do
|
||||
for j = 0, 13 do
|
||||
Interface.event_on_chunk_generated({surface = player.surface, area = {left_top = {x = -7 * 32 + i * 32, y = -7 * 32 + j * 32}}})
|
||||
end
|
||||
end
|
||||
game.print('chunks generated')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'spd',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
memory.boat.speed = 60
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'stp',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
memory.boat.speed = 0
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'rms',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local rms = 0
|
||||
local n = 100000
|
||||
local seed = Math.random(n^2)
|
||||
for i = 1,n do
|
||||
local noise = simplex_noise(i, 7.11, seed)
|
||||
rms = rms + noise^2
|
||||
end
|
||||
rms = rms/n
|
||||
game.print(rms)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'pro',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local global_memory = Memory.get_global_memory()
|
||||
|
||||
local proposal = {
|
||||
capacity_option = 3,
|
||||
difficulty_option = 2,
|
||||
-- mode_option = 'left',
|
||||
endorserindices = { 2 },
|
||||
name = "TestRun"
|
||||
}
|
||||
|
||||
global_memory.crewproposals[#global_memory.crewproposals + 1] = proposal
|
||||
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'lev',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Progression.go_from_currentdestination_to_sea()
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'hld',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Upgrades.execute_upgade(Upgrades.enum.EXTRA_HOLD)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'pwr',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Upgrades.execute_upgade(Upgrades.enum.MORE_POWER)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
commands.add_command(
|
||||
'score',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
game.print('faking a highscore...')
|
||||
Highscore.write_score(memory.secs_id, 'fakers', 0, 40, CoreData.version_float, 1, 1)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'scrget',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.print('running Highscore.load_in_scores()')
|
||||
Highscore.load_in_scores()
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'tim',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.current_destination().dynamic_data.timer = 88
|
||||
game.print('time set to 88 seconds')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'gld',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
memory.stored_fuel = memory.stored_fuel + 20000
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'bld',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
memory.classes_table = {[1] = 1}
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'rad',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Islands.spawn_enemy_boat(Boats.enum.RAFT)
|
||||
local boat = memory.enemyboats[1]
|
||||
Ai.spawn_boat_biters(boat, 0.89, Boats.get_scope(boat).Data.capacity, Boats.get_scope(boat).Data.width)
|
||||
game.print('enemy boat spawned')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'rad2',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Islands.spawn_enemy_boat(Boats.enum.RAFTLARGE)
|
||||
local boat = memory.enemyboats[1]
|
||||
Ai.spawn_boat_biters(boat, 0.89, Boats.get_scope(boat).Data.capacity, Boats.get_scope(boat).Data.width)
|
||||
game.print('large enemy boat spawned')
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'krk',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
Memory.set_working_id(1)
|
||||
local memory = Memory.get_crew_memory()
|
||||
Kraken.try_spawn_kraken()
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'1',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.speed = 1
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'2',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.speed = 2
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'4',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.speed = 4
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'8',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.speed = 8
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'16',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.speed = 16
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'32',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.speed = 32
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'64',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
game.speed = 64
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'ef1',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
Effects.worm_movement_effect(surface, {x = -45, y = 0}, false, true)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'ef2',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
Effects.worm_movement_effect(surface, {x = -45, y = 0}, false, false)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'ef3',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
Effects.worm_movement_effect(surface, {x = -45, y = 0}, true, false)
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'ef4',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
Effects.worm_emerge_effect(surface, {x = -45, y = 0})
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'ef5',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
local param = tostring(cmd.parameter)
|
||||
if check_admin(cmd) then
|
||||
local player = game.players[cmd.player_index]
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Common.current_destination().surface_name]
|
||||
Effects.biters_emerge(surface, {x = -30, y = 0})
|
||||
end
|
||||
end)
|
||||
|
||||
commands.add_command(
|
||||
'emoji',
|
||||
'is a dev command.',
|
||||
function(cmd)
|
||||
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)
|
||||
end
|
||||
end)
|
||||
end
|
1323
maps/pirates/common.lua
Normal file
1323
maps/pirates/common.lua
Normal file
File diff suppressed because it is too large
Load Diff
287
maps/pirates/coredata.lua
Normal file
287
maps/pirates/coredata.lua
Normal file
@ -0,0 +1,287 @@
|
||||
|
||||
local Math = require 'maps.pirates.math'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.scenario_id_name = 'pirates'
|
||||
Public.version_string = '1.1.1.5.4'
|
||||
Public.version_float = 1.1154
|
||||
|
||||
Public.blueprint_library_allowed = true
|
||||
Public.blueprint_importing_allowed = true
|
||||
|
||||
Public.rocket_silo_death_causes_loss = false
|
||||
|
||||
Public.victory_x = 1000
|
||||
|
||||
Public.total_max_biters = 2000
|
||||
|
||||
Public.lobby_surface_name = '000-000-Lobby'
|
||||
|
||||
Public.colors = {
|
||||
coal = {r=0.5, g=0.5, b=0.5},
|
||||
wood = {r=204, g=158, b=67},
|
||||
stone = {r=230, g=220, b=190},
|
||||
coin = {r=242, g=193, b=97},
|
||||
['raw-fish'] = {r=0, g=237, b=170},
|
||||
['iron-plate'] = {r=170, g=180, b=190},
|
||||
['iron-ore'] = {r=170, g=180, b=190},
|
||||
['copper-plate'] = {r=219, g=149, b=96},
|
||||
['copper-ore'] = {r=219, g=149, b=96},
|
||||
notify_error = {r=170, g=170, b=170},
|
||||
notify_player_expected = {r=255, g=231, b=46},
|
||||
notify_player_announce = {r=244, g=255, b=145},
|
||||
notify_game = {r=249, g=103, b=56},
|
||||
notify_lobby = {r=249, g=153, b=56},
|
||||
notify_force = {r=249, g=153, b=56},
|
||||
notify_force_light = {r=255, g=220, b=161},
|
||||
parrot = {r=87, g=255, b=148},
|
||||
notify_victory = {r=84, g=249, b=84},
|
||||
notify_gameover = {r=249, g=84, b=84},
|
||||
renderingtext_green = {r=88, g=219, b=88},
|
||||
renderingtext_yellow = {r=79, g=136, b=209},
|
||||
quartermaster_rendering = {r=237, g=157, b=45, a=0.15},
|
||||
}
|
||||
|
||||
Public.static_boat_floor = 'brown-refined-concrete'
|
||||
Public.moving_boat_floor = 'lab-dark-2'
|
||||
Public.world_concrete_tile = 'black-refined-concrete'
|
||||
Public.walkway_tile = 'orange-refined-concrete'
|
||||
Public.landing_tile = 'red-refined-concrete'
|
||||
Public.enemy_landing_tile = 'purple-refined-concrete'
|
||||
Public.overworld_loading_tile = 'yellow-refined-concrete'
|
||||
Public.overworld_presence_tile = 'green-refined-concrete'
|
||||
Public.kraken_tile = 'pink-refined-concrete'
|
||||
|
||||
Public.enemy_units = {
|
||||
'small-biter',
|
||||
'small-spitter',
|
||||
'medium-biter',
|
||||
'medium-spitter',
|
||||
'big-biter',
|
||||
'big-spitter',
|
||||
'behemoth-biter',
|
||||
'behemoth-spitter',
|
||||
}
|
||||
|
||||
Public.water_tile_names = {'water', 'deepwater', 'water-green', 'deepwater-green'}
|
||||
|
||||
Public.edgemost_tile_names = {'sand-1'}
|
||||
|
||||
Public.tiles_that_conflict_with_resource_layer = {'water', 'deepwater', 'water-green', 'deepwater-green', 'water-shallow', 'water-mud', 'out-of-map'}
|
||||
|
||||
Public.tiles_that_conflict_with_resource_layer_extended = {'water', 'deepwater', 'water-green', 'deepwater-green', 'water-shallow', 'water-mud', 'out-of-map', 'red-refined-concrete', 'brown-refined-concrete', 'orange-refined-concrete'}
|
||||
|
||||
Public.noworm_tile_names = {'red-refined-concrete', 'purple-refined-concrete', 'green-refined-concrete', 'orange-refined-concrete', 'brown-refined-concrete', 'lab-dark-2', 'sand-1', 'red-desert-3'}
|
||||
|
||||
Public.worm_solid_tile_names = {'black-refined-concrete', 'stone-path', 'concrete', 'refined-concrete', 'red-refined-concrete', 'purple-refined-concrete', 'brown-refined-concrete', 'lab-dark-2', 'sand-1', 'red-desert-3'}
|
||||
|
||||
Public.unteleportable_names = {'transport-belt', 'underground-belt', 'splitter', 'loader', 'fast-transport-belt', 'fast-underground-belt', 'fast-splitter', 'fast-loader', 'express-transport-belt', 'express-underground-belt', 'express-splitter', 'express-loader', 'pipe', 'pipe-to-ground', 'offshore-pump', 'chemical-plant', 'oil-refinery', 'flamethrower-turret', 'storage-tank', 'assembling-machine-2', 'assembling-machine-3', 'boiler', 'steam-engine', 'heat-exchanger', 'steam-turbine', 'pump', 'straight-rail', 'curved-rail', 'cargo-wagon', 'artillery-turret', 'electric-energy-interface', 'accumulator', 'linked-belt'}
|
||||
|
||||
|
||||
Public.comfy_emojis = {
|
||||
monkas = '<:monkas:555120573752279056>',
|
||||
trashbin = '<:trashbin:835887736253710396>',
|
||||
pogkot = '<:pogkot:763854655612518420>',
|
||||
goldenobese = '<:goldenobese:491135683508043786>',
|
||||
wut = '<:wut:493320605592977443>',
|
||||
smolfish = '<:smolfish:673942701682589731>',
|
||||
mjau = '<:mjau:789611417132073010>',
|
||||
spurdo = '<:spurdo:669546779360100382>',
|
||||
loops = '<:loops:783508194755346462>',
|
||||
ree1 = '<:ree1:555118905090244618>',
|
||||
derp = '<:derp:527570293850505266>',
|
||||
doge = '<:doge:491152224681066496>',
|
||||
yum1 = '<:yum1:740341272451219517>',
|
||||
feel = '<:feel:491147760553164800>',
|
||||
kewl = '<:kewl:837016976937189418>',
|
||||
}
|
||||
|
||||
Public.capacity_options = {
|
||||
{value = 2, icon = 'virtual-signal/signal-2', text = '2', text2 = '/2', text3 = '2'},
|
||||
{value = 4, icon = 'virtual-signal/signal-4', text = '4', text2 = '/4', text3 = '4'},
|
||||
{value = 8, icon = 'virtual-signal/signal-8', text = '8', text2 = '/8', text3 = '8'},
|
||||
{value = 24, icon = 'virtual-signal/signal-blue', text = '24', text2 = '/24', text3 = '24'},
|
||||
{value = 999, icon = 'virtual-signal/signal-white', text = 'Inf.', text2 = '', text3 = 'Inf'},
|
||||
-- {value = 64, icon = 'item/storage-tank', text = '64'},
|
||||
}
|
||||
Public.difficulty_options = {
|
||||
-- The difficulty values we currently offer
|
||||
|
||||
--For the value of Easy difficulty, we are pulled in two directions: We wish to make the game comfy to play for those who haven't played it, but we also wish to represent the game mechanics faithfully so that Normal is not a crazy distance away.
|
||||
{value = 0.55, icon = 'item/firearm-magazine', text = 'Easy', associated_color = {r = 50, g = 255, b = 50}},
|
||||
{value = 0.9, icon = 'item/piercing-rounds-magazine', text = 'Normal', associated_color = {r = 255, g = 255, b = 50}},
|
||||
{value = 1.5, icon = 'item/uranium-rounds-magazine', text = 'Hard', associated_color = {r = 255, g = 50, b = 50}},
|
||||
{value = 3, icon = 'item/atomic-bomb', text = 'Nightmare', associated_color = {r = 120, g = 35, b = 35}},
|
||||
}
|
||||
function Public.get_difficulty_name_from_value(difficulty_value)
|
||||
-- Functions will reference this when given a difficulty value and want to present a difficulty name to the player; just make it consistent with the above
|
||||
if difficulty_value <= 0.7 then
|
||||
return 'Easy'
|
||||
elseif difficulty_value < 1.3 then
|
||||
return 'Normal'
|
||||
elseif difficulty_value <= 2 then
|
||||
return 'Hard'
|
||||
else
|
||||
return 'Nightmare'
|
||||
end
|
||||
end
|
||||
|
||||
-- Public.mode_options = {
|
||||
-- left = {value = 'speedrun', icon = 'achievement/watch-your-step', text = 'Speedrun'},
|
||||
-- right = {value = 'infinity', icon = 'achievement/mass-production-1', text = 'Infinity'},
|
||||
-- }
|
||||
|
||||
Public.daynightcycle_types = {
|
||||
{displayname = 'Static', 0},
|
||||
{displayname = 'Slow Cyclic', ticksperday = 100000},
|
||||
{displayname = 'Cyclic', ticksperday = 80000},
|
||||
{displayname = 'Fast Cyclic', ticksperday = 60000},
|
||||
{displayname = 'Rapid Cyclic', ticksperday = 40000},
|
||||
}
|
||||
|
||||
Public.ore_types = {
|
||||
{name = 'iron-ore', sprite_name = 'entity/iron-ore'},
|
||||
{name = 'copper-ore', sprite_name = 'entity/copper-ore'},
|
||||
{name = 'coal', sprite_name = 'entity/coal'},
|
||||
{name = 'stone', sprite_name = 'entity/stone'},
|
||||
{name = 'uranium-ore', sprite_name = 'entity/uranium-ore'},
|
||||
{name = 'crude-oil', sprite_name = 'entity/crude-oil'},
|
||||
}
|
||||
|
||||
Public.cost_items = {
|
||||
{name = 'electronic-circuit', display_name = 'Electronic circuit', sprite_name = 'item/electronic-circuit', color={r=0,g=255,b=0}},
|
||||
{name = 'engine-unit', display_name = 'Engine unit', sprite_name = 'item/engine-unit', color={r=255,g=255,b=0}},
|
||||
{name = 'advanced-circuit', display_name = 'Advanced circuit', sprite_name = 'item/advanced-circuit', color={r=0,g=0,b=255}},
|
||||
{name = 'flying-robot-frame', display_name = 'Flying robot frame', sprite_name = 'item/flying-robot-frame', color={r=0,g=255,b=255}},
|
||||
{name = 'uranium-235', display_name = 'Uranium-235', sprite_name = 'item/uranium-235', color={r=0,g=255,b=0}},
|
||||
{name = 'fluid-wagon', display_name = 'Fluid Wagon', sprite_name = 'item/fluid-wagon', color={r=255,g=255,b=255}},
|
||||
}
|
||||
|
||||
Public.fallthrough_destination = {
|
||||
dynamic_data = {},
|
||||
static_params = {},
|
||||
type = 'Lobby',
|
||||
surface_name = Public.lobby_surface_name,
|
||||
}
|
||||
|
||||
-- hacked to make spitters 25% cheaper:
|
||||
Public.biterPollutionValues = {
|
||||
['behemoth-biter'] = 400,
|
||||
['behemoth-spitter'] = 150,
|
||||
['big-biter'] = 80,
|
||||
['big-spitter'] = 22,
|
||||
['medium-biter'] = 20,
|
||||
['medium-spitter'] = 9,
|
||||
['small-biter'] = 4,
|
||||
['small-spitter'] = 3
|
||||
}
|
||||
-- base game:
|
||||
-- Public.biterPollutionValues = {
|
||||
-- ['behemoth-biter'] = 400,
|
||||
-- ['behemoth-spitter'] = 200,
|
||||
-- ['big-biter'] = 80,
|
||||
-- ['big-spitter'] = 30,
|
||||
-- ['medium-biter'] = 20,
|
||||
-- ['medium-spitter'] = 12,
|
||||
-- ['small-biter'] = 4,
|
||||
-- ['small-spitter'] = 4
|
||||
-- }
|
||||
|
||||
Public.max_extra_seconds_at_sea = 8 * 60
|
||||
|
||||
Public.loco_bp_1 = [[0eNqV0ttqwzAMBuB30bVTVufsVxljpKloBYkcbLdrCH73Oi6UMrxDLm3zf7KEFjgMF5wMsQO1APWaLaj3BSyduBvWOzdPCArI4QgCuBvX06B7PWpHVwQvgPiIN1B7L/4Mmo6Gl4j0HwKQHTnCR+F4mD/5Mh7QBDNVUsCkbYhoXusEJmsFzKCqAGtDgegej2/rj76J8il+aX1EzvozWpcwm10ZVbkrfcLJ/+u0vzvF07EuTOd0dlkc0k9NJpFyI1KnkGrrZJp0R/XWyUQnLEJcFfWykgKuaGxMyGZf1K2sC5nnTVl5fwdTR+VL]]
|
||||
|
||||
function Public.Dock_iconized_map()
|
||||
local tiles = {}
|
||||
|
||||
for x = -15.5, 3.5 do
|
||||
for y = 19.5, 0.5, -1 do
|
||||
if (y <7 and y>2 and x == -2.5)
|
||||
or (y == 6.5 and x<2 and x>-6)
|
||||
then
|
||||
tiles[#tiles + 1] = {name = Public.walkway_tile, position = {x = x, y = y}}
|
||||
elseif y < 3 - Math.abs(x+5)^2/20 then --'island'
|
||||
if y < 0.5 and x<-3 and x>-7 then
|
||||
tiles[#tiles + 1] = {name = 'grass-1', position = {x = x, y = y}}
|
||||
elseif y < 3 + Math.abs(x+5)^2/10 then
|
||||
tiles[#tiles + 1] = {name = 'dirt-3', position = {x = x, y = y}}
|
||||
else
|
||||
tiles[#tiles + 1] = {name = 'dry-dirt', position = {x = x, y = y}}
|
||||
end
|
||||
elseif y<7 then
|
||||
tiles[#tiles + 1] = {name = 'water', position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
end
|
||||
return {
|
||||
tiles = tiles,
|
||||
entities = {},
|
||||
}
|
||||
end
|
||||
-- function Public.Dock_iconized_map()
|
||||
-- local tiles = {}
|
||||
|
||||
-- for x = -15.5, 3.5 do
|
||||
-- for y = -19.5, -0.5 do
|
||||
-- if (y >-7 and y<-2 and x == -2.5)
|
||||
-- or (y == -6.5 and x<2 and x>-6)
|
||||
-- then
|
||||
-- tiles[#tiles + 1] = {name = Public.walkway_tile, position = {x = x, y = y}}
|
||||
-- elseif y > -3 + Math.abs(x+5)^2/20 then --'island'
|
||||
-- if y > -0.5 and x<-3 and x>-7 then
|
||||
-- tiles[#tiles + 1] = {name = 'grass-1', position = {x = x, y = y}}
|
||||
-- elseif y > -3 + Math.abs(x+5)^2/10 then
|
||||
-- tiles[#tiles + 1] = {name = 'dirt-3', position = {x = x, y = y}}
|
||||
-- else
|
||||
-- tiles[#tiles + 1] = {name = 'dry-dirt', position = {x = x, y = y}}
|
||||
-- end
|
||||
-- elseif y>-7 then
|
||||
-- tiles[#tiles + 1] = {name = 'water', position = {x = x, y = y}}
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- return {
|
||||
-- tiles = tiles,
|
||||
-- entities = {},
|
||||
-- }
|
||||
-- end
|
||||
|
||||
|
||||
|
||||
function Public.Lobby_iconized_map()
|
||||
|
||||
local tiles = {}
|
||||
local width = 4
|
||||
-- local height = 20
|
||||
|
||||
for x = -100, width do
|
||||
for y = -35.5, 35.5 do
|
||||
local negx = width - x
|
||||
local negxnoisy = negx + Math.random(3)-2
|
||||
if negxnoisy >= 50 then
|
||||
tiles[#tiles + 1] = {name = 'grass-3', position = {x = x, y = y}}
|
||||
elseif negxnoisy >= 30 and (negxnoisy-30) >= Math.abs(y)^2/200 then
|
||||
tiles[#tiles + 1] = {name = 'dirt-4', position = {x = x, y = y}}
|
||||
elseif negxnoisy >= 15 and (negxnoisy-15) >= Math.abs(y)^2/150 then
|
||||
tiles[#tiles + 1] = {name = 'dirt-2', position = {x = x, y = y}}
|
||||
else
|
||||
if negx >= 5 and (negx-5) >= Math.abs(y)^2/100 then
|
||||
tiles[#tiles + 1] = {name = 'sand-2', position = {x = x, y = y}}
|
||||
elseif (negx <= 8 and Math.abs(y)<1) or (negx < 1 and Math.abs(y)<3) then
|
||||
tiles[#tiles + 1] = {name = Public.walkway_tile, position = {x = x, y = y}}
|
||||
else
|
||||
tiles[#tiles + 1] = {name = 'water', position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return {
|
||||
tiles = tiles,
|
||||
entities = {},
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
return Public
|
1004
maps/pirates/crew.lua
Normal file
1004
maps/pirates/crew.lua
Normal file
File diff suppressed because it is too large
Load Diff
14
maps/pirates/custom_events.lua
Normal file
14
maps/pirates/custom_events.lua
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local Public = {}
|
||||
|
||||
-- just beginning this, gotta finish reformulating the gui updates in terms of events:
|
||||
|
||||
local enum = {
|
||||
update_crew_progress_gui = Event.generate_event_name('update_crew_progress_gui'),
|
||||
update_crew_fuel_gui = Event.generate_event_name('update_crew_fuel_gui'),
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
return Public
|
122
maps/pirates/effects.lua
Normal file
122
maps/pirates/effects.lua
Normal file
@ -0,0 +1,122 @@
|
||||
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Token = require 'utils.token'
|
||||
local Task = require 'utils.task'
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
||||
function Public.worm_movement_effect(surface, position, solid_ground, big_bool)
|
||||
if not (surface and surface.valid) then return end
|
||||
|
||||
if solid_ground then big_bool = false end
|
||||
|
||||
local number, rmax, particles, sound
|
||||
if big_bool then
|
||||
number = 80
|
||||
rmax = 4
|
||||
particles = {'huge-rock-stone-particle-big', 'huge-rock-stone-particle-medium', 'red-desert-1-stone-particle-medium'}
|
||||
-- sound = 'utility/build_blueprint_large'
|
||||
sound = 'utility/build_blueprint_large'
|
||||
else
|
||||
number = 40
|
||||
rmax = 2.5
|
||||
particles = {'huge-rock-stone-particle-medium', 'red-desert-1-stone-particle-medium', 'red-desert-1-stone-particle-small'}
|
||||
sound = 'utility/build_blueprint_medium'
|
||||
end
|
||||
|
||||
if solid_ground then
|
||||
particles = {'refined-concrete-stone-particle-medium', 'refined-concrete-stone-particle-small'}
|
||||
sound = 'utility/build_blueprint_small'
|
||||
end
|
||||
|
||||
|
||||
local function p(r, theta) return {x = position.x + r*Math.sin(theta), y = position.y + r*Math.cos(theta)} end
|
||||
|
||||
for i=1,number do
|
||||
local r = rmax * Math.sqrt(Math.random())
|
||||
local theta = Math.random()*6.283
|
||||
local name = particles[Math.random(#particles)]
|
||||
local _p = p(r,theta)
|
||||
|
||||
surface.create_particle{name = name, position = _p, movement = {0/10, 0/10}, height = 0, vertical_speed = 0.02 + Math.sqrt(rmax - r)*rmax/50, frame_speed = 1}
|
||||
|
||||
if i<=5 then
|
||||
surface.play_sound{path = sound, position = _p, override_sound_type = 'walking', volume_modifier=0.75}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.worm_emerge_effect(surface, position)
|
||||
if not (surface and surface.valid) then return end
|
||||
if position then
|
||||
local function p(r, theta) return {x = position.x + r*Math.sin(theta), y = position.y + r*Math.cos(theta)} end
|
||||
|
||||
for theta=0,6,0.5 do
|
||||
local r = 3
|
||||
surface.create_entity{name = 'blood-explosion-huge', position = p(r,theta), color={1,1,1}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.biters_emerge(surface, position)
|
||||
if not (surface and surface.valid) then return end
|
||||
surface.create_entity{name = 'spitter-spawner-die', position = position}
|
||||
end
|
||||
|
||||
function Public.kraken_effect_1(surface, position, angle)
|
||||
if not (surface and surface.valid) then return end
|
||||
local r = 9
|
||||
local p = {position.x + r*Math.sin(angle), position.y + r*Math.cos(angle)}
|
||||
surface.create_entity{name = 'blood-explosion-huge', position = p, color={1,1,1}}
|
||||
end
|
||||
|
||||
function Public.kraken_effect_2(surface, position)
|
||||
if not (surface and surface.valid) then return end
|
||||
surface.create_entity{name = 'blood-explosion-big', position = position, color={1,1,1}}
|
||||
end
|
||||
|
||||
local kraken_effect_3_token =
|
||||
Token.register(
|
||||
function(data)
|
||||
Public.kraken_effect_3(data.surface, data.position, data.r)
|
||||
end
|
||||
)
|
||||
function Public.kraken_effect_3(surface, position, r)
|
||||
r = r or 3
|
||||
if not (surface and surface.valid) then return end
|
||||
|
||||
for theta=0,6.283,6.283/32 do
|
||||
local p = {position.x + r*Math.sin(theta), position.y + r*Math.cos(theta)}
|
||||
surface.create_entity{name = 'water-splash', position = p, color={1,1,1}}
|
||||
end
|
||||
|
||||
local rmax = 100
|
||||
if r < rmax then
|
||||
Task.set_timeout_in_ticks(4, kraken_effect_3_token, {surface = surface, position = position, r = r + 2})
|
||||
end
|
||||
end
|
||||
|
||||
function Public.kraken_effect_4(surface, position)
|
||||
if not (surface and surface.valid) then return end
|
||||
local r = 6
|
||||
for theta=0,6.283,6.283/32 do
|
||||
local p = {position.x + r*Math.sin(theta), position.y + r*Math.cos(theta)}
|
||||
surface.create_entity{name = 'blood-explosion-big', position = p, color={1,1,1}}
|
||||
end
|
||||
end
|
||||
|
||||
function Public.kraken_effect_5(surface, position)
|
||||
if not (surface and surface.valid) then return end
|
||||
local r = 6
|
||||
for theta=0,6.283,6.283/32 do
|
||||
local p = {position.x + r*Math.sin(theta), position.y + r*Math.cos(theta)}
|
||||
surface.create_entity{name = 'blood-explosion-huge', position = p, color={1,1,1}}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
59
maps/pirates/gui/color.lua
Normal file
59
maps/pirates/gui/color.lua
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
local GuiCommon = require 'maps.pirates.gui.common'
|
||||
local PlayerColors = require 'maps.pirates.player_colors'
|
||||
local Public = {}
|
||||
|
||||
local window_name = 'color'
|
||||
|
||||
function Public.toggle_window(player)
|
||||
local flow, flow2
|
||||
|
||||
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 = 'Colors!'
|
||||
flow.style.width = 500
|
||||
flow.style.height = 500
|
||||
|
||||
-- local label = ''
|
||||
-- for i, v in ipairs(PlayerColors.names) do
|
||||
-- if i>1 then label = label .. ', ' end
|
||||
-- local c = PlayerColors.colors[v]
|
||||
-- label = label .. ', [color=' .. c.r .. ',' .. c.g .. ',' .. c.b .. ']' .. v .. '[/color]'
|
||||
-- -- label = label .. v
|
||||
-- end
|
||||
-- log(label)
|
||||
|
||||
|
||||
flow2 = flow.add({
|
||||
name = 'colors',
|
||||
type = 'text-box',
|
||||
text = PlayerColors.printable,
|
||||
})
|
||||
flow2.word_wrap = true
|
||||
flow2.read_only = true
|
||||
flow2.selectable = true
|
||||
flow2.style.width = 450
|
||||
flow2.style.height = 400
|
||||
|
||||
GuiCommon.flow_add_close_button(flow, window_name .. '_piratebutton')
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- function Public.regular_update(player)
|
||||
|
||||
-- end
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
end
|
||||
|
||||
|
||||
-- function Public.click(event)
|
||||
-- end
|
||||
|
||||
return Public
|
531
maps/pirates/gui/common.lua
Normal file
531
maps/pirates/gui/common.lua
Normal file
@ -0,0 +1,531 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Crew = require 'maps.pirates.crew'
|
||||
-- local Progression = require 'maps.pirates.progression'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
local Shop = require 'maps.pirates.shop.shop'
|
||||
local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
||||
Public.bold_font_color = {255, 230, 192}
|
||||
Public.default_font_color = {1, 1, 1}
|
||||
Public.section_header_font_color = {r=0.40, g=0.80, b=0.60}
|
||||
Public.subsection_header_font_color = {229, 255, 242}
|
||||
Public.friendly_font_color = {240, 200, 255}
|
||||
Public.sufficient_font_color = {66, 220, 124}
|
||||
Public.insufficient_font_color = {1, 0.62, 0.19}
|
||||
Public.achieved_font_color = {227, 250, 192}
|
||||
|
||||
Public.fuel_color_1 = {r=255, g=255, b=255}
|
||||
Public.fuel_color_2 = {r=255, g=0, b=60}
|
||||
|
||||
Public.rage_font_color_1 = {r=1, g=1, b=1}
|
||||
Public.rage_font_color_2 = {r=1, g=0.5, b=0.1}
|
||||
Public.rage_font_color_3 = {r=1, g=0.1, b=0.05}
|
||||
|
||||
|
||||
|
||||
Public.default_window_positions = {
|
||||
runs = {x = 10, y = 48},
|
||||
crew = {x = 40, y = 48},
|
||||
progress = {x = 250, y = 48},
|
||||
fuel = {x = 468, y = 48},
|
||||
minimap = {x = 10, y = 48},
|
||||
color = {x = 160, y = 96},
|
||||
}
|
||||
|
||||
|
||||
function Public.new_window(player, name)
|
||||
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local gui_memory = global_memory.player_gui_memories[player.index]
|
||||
local flow
|
||||
|
||||
flow = player.gui.screen.add{
|
||||
type = 'frame',
|
||||
name = name .. '_piratewindow',
|
||||
direction = 'vertical'
|
||||
}
|
||||
|
||||
if gui_memory and gui_memory[name] and gui_memory[name].position then
|
||||
flow.location = gui_memory[name].position
|
||||
else
|
||||
flow.location = Public.default_window_positions[name]
|
||||
end
|
||||
|
||||
flow.style = 'map_details_frame'
|
||||
flow.style.minimal_width = 210
|
||||
flow.style.natural_width = 210
|
||||
flow.style.maximal_width = 270
|
||||
flow.style.minimal_height = 80
|
||||
flow.style.natural_height = 80
|
||||
flow.style.maximal_height = 700
|
||||
flow.style.padding = 10
|
||||
|
||||
return flow
|
||||
end
|
||||
|
||||
|
||||
function Public.update_gui_memory(player, namespace, key, value)
|
||||
local global_memory = Memory.get_global_memory()
|
||||
if not global_memory.player_gui_memories[player.index] then
|
||||
global_memory.player_gui_memories[player.index] = {}
|
||||
end
|
||||
local gui_memory = global_memory.player_gui_memories[player.index]
|
||||
if not gui_memory[namespace] then
|
||||
gui_memory[namespace] = {}
|
||||
end
|
||||
gui_memory[namespace][key] = value
|
||||
end
|
||||
|
||||
|
||||
function Public.flow_add_floating_sprite_button(flow1, button_name, width)
|
||||
width = width or 40
|
||||
local flow2, flow3
|
||||
|
||||
flow2 = flow1.add({
|
||||
name = button_name .. '_frame',
|
||||
type = 'frame',
|
||||
})
|
||||
flow2.style.height = 40
|
||||
flow2.style.margin = 0
|
||||
flow2.style.left_padding = -4
|
||||
flow2.style.top_padding = -4
|
||||
flow2.style.right_margin = -2
|
||||
flow2.style.width = width
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = button_name,
|
||||
type = 'sprite-button',
|
||||
})
|
||||
flow3.style.height = 40
|
||||
flow3.style.width = width
|
||||
-- flow3.style.padding = -4
|
||||
|
||||
return flow3
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.flow_add_floating_button(flow1, button_name)
|
||||
local flow2, flow3
|
||||
|
||||
flow2 = flow1.add({
|
||||
name = button_name .. '_flow_1',
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow2.style.height = 40
|
||||
-- flow2.style.left_padding = 4
|
||||
-- flow2.style.top_padding = 0
|
||||
-- flow2.style.right_margin = -2
|
||||
flow2.style.natural_width = 40
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = button_name,
|
||||
type = 'button',
|
||||
})
|
||||
flow3.style = 'dark_rounded_button'
|
||||
-- flow3.style.minimal_width = 60
|
||||
-- flow3.style.natural_width = 60
|
||||
flow3.style.minimal_height = 40
|
||||
flow3.style.maximal_height = 40
|
||||
flow3.style.left_padding = 10
|
||||
flow3.style.right_padding = 4
|
||||
flow3.style.top_padding = 3
|
||||
-- flow3.style.padding = -4
|
||||
flow3.style.natural_width = 40
|
||||
flow3.style.horizontally_stretchable = true
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = button_name .. '_flow_2',
|
||||
type = 'flow',
|
||||
})
|
||||
flow3.style.natural_width = 20
|
||||
flow3.style.top_margin = -37
|
||||
flow3.style.left_margin = 10
|
||||
flow3.style.right_margin = 9
|
||||
flow3.ignored_by_interaction=true
|
||||
|
||||
return flow3
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.flow_add_shop_item(flow, name)
|
||||
local flow2, flow3
|
||||
|
||||
local shop_data_1 = Shop.Captains.main_shop_data_1
|
||||
local shop_data_2 = Shop.Captains.main_shop_data_2
|
||||
local trade_data = shop_data_1[name] or shop_data_2[name]
|
||||
if not trade_data then return end
|
||||
|
||||
flow2 = flow.add({
|
||||
name = name,
|
||||
type = 'flow',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
flow2.style.top_margin = 3
|
||||
flow2.style.horizontal_align = 'center'
|
||||
flow2.style.vertical_align = 'center'
|
||||
flow2.tooltip = trade_data.tooltip
|
||||
|
||||
|
||||
for k, v in pairs(trade_data.what_you_get_sprite_buttons) do
|
||||
flow3 = flow2.add({
|
||||
type = 'sprite-button',
|
||||
name = k,
|
||||
sprite = k,
|
||||
enabled = false,
|
||||
})
|
||||
flow3.style.minimal_height = 40
|
||||
flow3.style.maximal_height = 40
|
||||
if v == false then
|
||||
flow3.number = nil
|
||||
else
|
||||
flow3.number = v
|
||||
end
|
||||
flow3.tooltip = trade_data.tooltip
|
||||
end
|
||||
|
||||
flow3 = flow2.add({
|
||||
type = 'label',
|
||||
name = 'for',
|
||||
caption = 'for'
|
||||
})
|
||||
flow3.style.font = 'default-large'
|
||||
flow3.style.font_color = Public.default_font_color
|
||||
flow3.tooltip = trade_data.tooltip
|
||||
|
||||
for k, _ in pairs(trade_data.base_cost) do
|
||||
flow3 = flow2.add({
|
||||
name = 'cost_' .. k,
|
||||
type = 'sprite-button',
|
||||
enabled = false,
|
||||
})
|
||||
flow3.style.minimal_height = 40
|
||||
flow3.style.maximal_height = 40
|
||||
flow3.tooltip = trade_data.tooltip
|
||||
if k == 'fuel' then
|
||||
flow3.sprite = 'item/coal'
|
||||
elseif k == 'coins' then
|
||||
flow3.sprite = 'item/coin'
|
||||
elseif k == 'iron_plates' then
|
||||
flow3.sprite = 'item/iron-plate'
|
||||
elseif k == 'copper_plates' then
|
||||
flow3.sprite = 'item/copper-plate'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'spacing',
|
||||
type = 'flow',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
flow3.style.horizontally_stretchable = true
|
||||
|
||||
flow3 = flow2.add({
|
||||
type = 'sprite-button',
|
||||
name = 'buy_button',
|
||||
caption = 'Buy'
|
||||
})
|
||||
flow3.style.font = 'default-large'
|
||||
flow3.style.font_color = Public.default_font_color
|
||||
flow3.style.height = 32
|
||||
flow3.style.width = 50
|
||||
flow3.style.padding = 0
|
||||
flow3.style.margin = 0
|
||||
|
||||
return flow2
|
||||
end
|
||||
|
||||
|
||||
function Public.flow_add_section(flow, name, caption)
|
||||
local flow2, flow3
|
||||
|
||||
flow2 = flow.add({
|
||||
name = name,
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow2.style.bottom_margin = 5
|
||||
|
||||
flow3 = flow2.add({
|
||||
type = 'label',
|
||||
name = 'header',
|
||||
caption = caption
|
||||
})
|
||||
flow3.style.font = 'heading-2'
|
||||
flow3.style.font_color = Public.section_header_font_color
|
||||
flow3.style.maximal_width = 300
|
||||
-- flow3.style.maximal_width = 220
|
||||
-- flow3.style.single_line = false
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'body',
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow3.style.left_margin = 5
|
||||
|
||||
return flow3
|
||||
end
|
||||
|
||||
|
||||
function Public.flow_add_subpanel(flow, name)
|
||||
local flow2
|
||||
|
||||
flow2 = flow.add({
|
||||
name = name,
|
||||
type = 'frame',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow2.style = 'subpanel_frame'
|
||||
flow2.style.natural_width = 100
|
||||
flow2.style.top_padding = -2
|
||||
flow2.style.top_margin = -8
|
||||
|
||||
return flow2
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.flow_add_close_button(flow, close_button_name)
|
||||
local flow2, flow3, flow4
|
||||
|
||||
flow2 = flow.add({
|
||||
name = 'close_button_flow',
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow2.style.top_margin = -3
|
||||
flow2.style.bottom_margin = -3
|
||||
|
||||
flow3 = flow2.add{type="flow", name='hflow', direction="horizontal"}
|
||||
flow3.style.vertical_align = 'center'
|
||||
|
||||
flow4 = flow3.add{type="flow", name='spacing', direction="horizontal"}
|
||||
flow4.style.horizontally_stretchable = true
|
||||
|
||||
flow4 = flow3.add({
|
||||
type = 'button',
|
||||
name = close_button_name,
|
||||
caption = 'Close',
|
||||
})
|
||||
flow4.style = 'back_button'
|
||||
flow4.style.minimal_width = 90
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.height = 28
|
||||
flow4.style.horizontal_align = 'center'
|
||||
|
||||
return flow3
|
||||
end
|
||||
|
||||
|
||||
function Public.crew_overall_state_bools(player_index)
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
--*** PLAYER STATUS ***--
|
||||
|
||||
local ret = {
|
||||
adventuring = false,
|
||||
spectating = false,
|
||||
endorsing = false,
|
||||
proposing = false,
|
||||
sloops_full = false,
|
||||
needs_more_capacity = false,
|
||||
crew_count_capped = false,
|
||||
needs_more_endorsers = false,
|
||||
leaving = false,
|
||||
proposal_can_launch = false,
|
||||
}
|
||||
if memory.crewstatus == Crew.enum.ADVENTURING then
|
||||
for _, playerindex in pairs(memory.crewplayerindices) do
|
||||
if player_index == playerindex then ret.adventuring = true end
|
||||
end
|
||||
for _, playerindex in pairs(memory.spectatorplayerindices) do
|
||||
if player_index == playerindex then ret.spectating = true end
|
||||
end
|
||||
end
|
||||
if memory.crewstatus == nil then
|
||||
for _, crewid in pairs(global_memory.crew_active_ids) do
|
||||
if global_memory.crew_memories[crewid].crewstatus == Crew.enum.LEAVING_INITIAL_DOCK then
|
||||
for _, endorser_index in pairs(global_memory.crew_memories[crewid].original_proposal.endorserindices) do
|
||||
if endorser_index == player_index then ret.leaving = true end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, proposal in pairs(global_memory.crewproposals) do
|
||||
if #proposal.endorserindices > 0 and proposal.endorserindices[1] == player_index then
|
||||
ret.proposing = true
|
||||
if #global_memory.crew_active_ids >= 3 then
|
||||
ret.sloops_full = true
|
||||
elseif #global_memory.crew_active_ids >= global_memory.active_crews_cap then
|
||||
ret.crew_count_capped = true
|
||||
elseif global_memory.active_crews_cap > 1 and #global_memory.crew_active_ids == (global_memory.active_crews_cap - 1) and not ((global_memory.crew_memories[1] and global_memory.crew_memories[1].capacity >= Common.minimum_run_capacity_to_enforce_space_for) or (global_memory.crew_memories[2] and global_memory.crew_memories[2].capacity >= Common.minimum_run_capacity_to_enforce_space_for) or (global_memory.crew_memories[3] and global_memory.crew_memories[3].capacity >= Common.minimum_run_capacity_to_enforce_space_for)) and not (CoreData.capacity_options[proposal.capacity_option].value >= Common.minimum_run_capacity_to_enforce_space_for) then
|
||||
ret.needs_more_capacity = true
|
||||
elseif proposal.endorserindices and #global_memory.crew_active_ids > 0 and #proposal.endorserindices < Math.min(4, Math.ceil((#game.connected_players or 0)/5)) then
|
||||
ret.needs_more_endorsers = true
|
||||
end
|
||||
if (not (ret.sloops_full or ret.needs_more_capacity or ret.needs_more_endorsers or ret.crew_count_capped)) then
|
||||
ret.proposal_can_launch = true
|
||||
end
|
||||
end
|
||||
for _, i in pairs(proposal.endorserindices) do
|
||||
if player_index == i then ret.endorsing = true end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.player_and_crew_state_bools(player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
-- if memory.player_and_crew_state_bools_memoized and memory.player_and_crew_state_bools_memoized.tick > game.tick - 30 then -- auto-memoize and only update every half-second
|
||||
-- return memory.player_and_crew_state_bools_memoized.ret
|
||||
-- else
|
||||
local destination = Common.current_destination()
|
||||
local dynamic_data = destination.dynamic_data --assumes this always exists
|
||||
|
||||
local in_crowsnest_bool, in_hold_bool, in_cabin_bool, onmap_bool, eta_bool, approaching_bool, retreating_bool, atsea_sailing_bool, landed_bool, quest_bool, silo_bool, charged_bool, launched_bool, captain_bool, atsea_loading_bool, character_on_deck_bool, on_deck_standing_near_loco_bool, on_deck_standing_near_cabin_bool, on_deck_standing_near_crowsnest_bool, cost_bool, cost_includes_rocket_launch_bool, approaching_dock_bool, leaving_dock_bool, leave_anytime_bool
|
||||
|
||||
captain_bool = Common.is_captain(player)
|
||||
|
||||
in_crowsnest_bool = string.sub(player.surface.name, 9, 17) == 'Crowsnest'
|
||||
in_hold_bool = string.sub(player.surface.name, 9, 12) == 'Hold'
|
||||
in_cabin_bool = string.sub(player.surface.name, 9, 13) == 'Cabin'
|
||||
|
||||
onmap_bool = destination.surface_name and (player.surface.name == destination.surface_name or (
|
||||
memory.boat and memory.boat.surface_name == destination.surface_name and (in_crowsnest_bool or in_hold_bool or in_cabin_bool)
|
||||
))
|
||||
|
||||
if destination then
|
||||
eta_bool = dynamic_data.time_remaining and dynamic_data.time_remaining > 0 and onmap_bool
|
||||
approaching_bool = memory.boat and memory.boat.state == Boats.enum_state.APPROACHING and onmap_bool
|
||||
retreating_bool = memory.boat and memory.boat.state == Boats.enum_state.RETREATING and onmap_bool
|
||||
-- approaching_bool = memory.boat and memory.boat.state == Boats.enum_state.APPROACHING
|
||||
atsea_sailing_bool = memory.boat and memory.boat.state == Boats.enum_state.ATSEA_SAILING
|
||||
landed_bool = memory.boat and memory.boat.state == Boats.enum_state.LANDED
|
||||
quest_bool = (dynamic_data.quest_type ~= nil) and onmap_bool
|
||||
silo_bool = dynamic_data.rocketsilos and dynamic_data.rocketsilos[1] and dynamic_data.rocketsilos[1].valid and onmap_bool
|
||||
charged_bool = dynamic_data.silocharged
|
||||
launched_bool = dynamic_data.rocketlaunched
|
||||
|
||||
cost_bool = destination.static_params.base_cost_to_undock and (not atsea_sailing_bool) and (not retreating_bool)
|
||||
cost_includes_rocket_launch_bool = cost_bool and destination.static_params.base_cost_to_undock['launch_rocket']
|
||||
|
||||
leave_anytime_bool = (landed_bool and not (eta_bool or cost_bool))
|
||||
end
|
||||
|
||||
if memory.boat then
|
||||
atsea_loading_bool = memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP and memory.loadingticks
|
||||
|
||||
character_on_deck_bool = player.character and player.character.position and player.surface.name and player.surface.name == memory.boat.surface_name
|
||||
|
||||
if character_on_deck_bool then
|
||||
local BoatData = Boats.get_scope(memory.boat).Data
|
||||
|
||||
on_deck_standing_near_loco_bool = Math.distance(player.character.position, Math.vector_sum(memory.boat.position, BoatData.loco_pos)) < 3
|
||||
|
||||
on_deck_standing_near_cabin_bool = Math.distance(player.character.position, Math.vector_sum(memory.boat.position, BoatData.cabin_car)) < 2.5
|
||||
|
||||
on_deck_standing_near_crowsnest_bool = Math.distance(player.character.position, Math.vector_sum(memory.boat.position, BoatData.crowsnest_center)) < 2.7
|
||||
end
|
||||
|
||||
approaching_dock_bool = destination.type == Surfaces.enum.DOCK and memory.boat.state == Boats.enum_state.APPROACHING
|
||||
leaving_dock_bool = destination.type == Surfaces.enum.DOCK and memory.boat.state == Boats.enum_state.LEAVING_DOCK
|
||||
end
|
||||
|
||||
local ret = {
|
||||
in_crowsnest_bool = in_crowsnest_bool,
|
||||
in_hold_bool = in_hold_bool,
|
||||
in_cabin_bool = in_cabin_bool,
|
||||
-- onmap_bool = onmap_bool,
|
||||
eta_bool = eta_bool,
|
||||
approaching_bool = approaching_bool,
|
||||
retreating_bool = retreating_bool,
|
||||
atsea_sailing_bool = atsea_sailing_bool,
|
||||
-- landed_bool = landed_bool,
|
||||
quest_bool = quest_bool,
|
||||
silo_bool = silo_bool,
|
||||
charged_bool = charged_bool,
|
||||
launched_bool = launched_bool,
|
||||
captain_bool = captain_bool,
|
||||
atsea_loading_bool = atsea_loading_bool,
|
||||
-- character_on_deck_bool = character_on_deck_bool,
|
||||
on_deck_standing_near_loco_bool = on_deck_standing_near_loco_bool,
|
||||
on_deck_standing_near_cabin_bool = on_deck_standing_near_cabin_bool,
|
||||
on_deck_standing_near_crowsnest_bool = on_deck_standing_near_crowsnest_bool,
|
||||
cost_bool = cost_bool,
|
||||
cost_includes_rocket_launch_bool = cost_includes_rocket_launch_bool,
|
||||
approaching_dock_bool = approaching_dock_bool,
|
||||
leaving_dock_bool = leaving_dock_bool,
|
||||
leave_anytime_bool = leave_anytime_bool
|
||||
}
|
||||
|
||||
-- memory.player_and_crew_state_bools_memoized = {ret = ret, tick = game.tick}
|
||||
|
||||
return ret
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.update_listbox(listbox, table)
|
||||
-- pass a table of strings of the form {'locale', unique_id, ...}
|
||||
|
||||
-- remove any that shouldn't be there
|
||||
local marked_for_removal = {}
|
||||
for index, item in pairs(listbox.items) do
|
||||
local exists = false
|
||||
for _, i in pairs(table) do
|
||||
if tostring(i[2]) == item[2] then
|
||||
exists = true
|
||||
end
|
||||
end
|
||||
if exists == false then
|
||||
marked_for_removal[#marked_for_removal + 1] = index
|
||||
end
|
||||
end
|
||||
for i = #marked_for_removal, 1, -1 do
|
||||
listbox.remove_item(marked_for_removal[i])
|
||||
end
|
||||
|
||||
local indexalreadyat
|
||||
for _, i in pairs(table) do
|
||||
local contained = false
|
||||
for index, item in pairs(listbox.items) do
|
||||
if tostring(i[2]) == item[2] then
|
||||
contained = true
|
||||
indexalreadyat = index
|
||||
end
|
||||
end
|
||||
|
||||
if contained then
|
||||
listbox.set_item(indexalreadyat, i)
|
||||
else
|
||||
listbox.add_item(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
666
maps/pirates/gui/crew.lua
Normal file
666
maps/pirates/gui/crew.lua
Normal file
@ -0,0 +1,666 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
local Roles = require 'maps.pirates.roles.roles'
|
||||
local Classes = require 'maps.pirates.roles.classes'
|
||||
local Crew = require 'maps.pirates.crew'
|
||||
-- local Progression = require 'maps.pirates.progression'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
-- local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local GuiCommon = require 'maps.pirates.gui.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
local Server = require 'utils.server'
|
||||
local Public = {}
|
||||
|
||||
|
||||
local window_name = 'crew'
|
||||
|
||||
|
||||
function Public.toggle_window(player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local flow, flow2, flow3, flow4
|
||||
|
||||
--*** OVERALL FLOW ***--
|
||||
if player.gui.screen[window_name .. '_piratewindow'] then player.gui.screen[window_name .. '_piratewindow'].destroy() return end
|
||||
|
||||
if not memory.id then return end
|
||||
|
||||
flow = GuiCommon.new_window(player, window_name)
|
||||
flow.caption = 'Crew'
|
||||
|
||||
--*** PARAMETERS OF RUN ***--
|
||||
|
||||
flow2 = flow.add({
|
||||
name = 'crew_capacity_and_difficulty',
|
||||
type = 'label',
|
||||
})
|
||||
flow2.style.left_margin = 5
|
||||
flow2.style.top_margin = 0
|
||||
flow2.style.bottom_margin = -3
|
||||
flow2.style.single_line = false
|
||||
flow2.style.maximal_width = 190
|
||||
flow2.style.font = 'default'
|
||||
|
||||
flow2 = flow.add({
|
||||
name = 'crew_age',
|
||||
type = 'label',
|
||||
})
|
||||
flow2.style.left_margin = 5
|
||||
flow2.style.top_margin = -3
|
||||
flow2.style.bottom_margin = 0
|
||||
flow2.style.single_line = true
|
||||
flow2.style.maximal_width = 200
|
||||
flow2.style.font = 'default'
|
||||
|
||||
-- flow2 = flow.add({
|
||||
-- name = 'crew_difficulty',
|
||||
-- type = 'label',
|
||||
-- })
|
||||
-- flow2.style.left_margin = 5
|
||||
-- flow2.style.top_margin = -3
|
||||
-- flow2.style.bottom_margin = 0
|
||||
-- flow2.style.single_line = false
|
||||
-- flow2.style.maximal_width = 190
|
||||
-- flow2.style.font = 'default'
|
||||
|
||||
|
||||
--*** MEMBERSHIP BUTTONS ***--
|
||||
|
||||
flow2 = flow.add({
|
||||
name = 'membership_buttons',
|
||||
type = 'flow',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'leave_crew',
|
||||
type = 'button',
|
||||
caption = 'Quit Crew',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Return to the lobby.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'leave_spectators',
|
||||
type = 'button',
|
||||
caption = 'Return to Lobby',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'spectator_join_crew',
|
||||
type = 'button',
|
||||
caption = 'Join Crew',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'crewmember_join_spectators',
|
||||
type = 'button',
|
||||
caption = 'Spectate',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'You won\t be able to rejoin the crew for a short while after you do this.'
|
||||
|
||||
--*** MEMBERS AND SPECTATORS ***--
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'members', 'Crew Members')
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'members_listbox',
|
||||
type = 'list-box',
|
||||
})
|
||||
flow3.style.margin = 2
|
||||
flow3.style.maximal_height = 350
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'class_renounce',
|
||||
type = 'button',
|
||||
caption = 'Give Up Class',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'The class will become available for other crewmembers to take.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'officer_resign',
|
||||
type = 'button',
|
||||
caption = 'Resign as Officer',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Give up the officer role.'
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'spectators', 'Spectators')
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'spectators_listbox',
|
||||
type = 'list-box',
|
||||
})
|
||||
flow3.style.margin = 2
|
||||
flow3.style.maximal_height = 150
|
||||
|
||||
--*** DIFFICULTY VOTE ***--
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'difficulty_vote', 'Vote for Difficulty')
|
||||
|
||||
for i, o in ipairs(CoreData.difficulty_options) do
|
||||
flow3 = flow2.add({
|
||||
name = 'difficulty_option_' .. i,
|
||||
type = 'button',
|
||||
caption = o.text,
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
end
|
||||
|
||||
--*** SPARE CLASSES ***--
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'spare_classes', 'Spare Classes')
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'list',
|
||||
type = 'label',
|
||||
})
|
||||
flow3.style.left_margin = 5
|
||||
flow3.style.top_margin = -3
|
||||
flow3.style.bottom_margin = -3
|
||||
flow3.style.single_line = false
|
||||
flow3.style.maximal_width = 160
|
||||
flow3.style.font = 'default-dropdown'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'assign_flow',
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow3.style.top_margin = 3
|
||||
|
||||
for _, c in ipairs(Classes.Class_List) do
|
||||
flow4 = flow3.add({
|
||||
name = 'assign_class_' .. c,
|
||||
type = 'button',
|
||||
caption = 'Give class: ' .. Classes.display_form[c],
|
||||
})
|
||||
flow4.style.minimal_width = 95
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow4.tooltip = 'Give the selected player the class ' .. Classes.display_form[c] .. '.\n\n Class description: ' .. Classes.explanation[c]
|
||||
-- flow4.tooltip = 'Give this class to the selected player.'
|
||||
end
|
||||
|
||||
for _, c in ipairs(Classes.Class_List) do
|
||||
flow4 = flow3.add({
|
||||
name = 'selfassign_class_' .. c,
|
||||
type = 'button',
|
||||
caption = 'Take class: ' .. Classes.display_form[c],
|
||||
})
|
||||
flow4.style.minimal_width = 95
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow4.tooltip = 'Give yourself the spare class ' .. Classes.display_form[c] .. '.\n\nClass description: ' .. Classes.explanation[c]
|
||||
end
|
||||
|
||||
--*** CAPTAIN's ACTIONS ***--
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'captain', 'Captain\'s Actions')
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'capn_disband_crew',
|
||||
type = 'button',
|
||||
caption = 'Disband Crew',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'End the run. You will be prompted again after clicking.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'capn_disband_are_you_sure',
|
||||
type = 'button',
|
||||
caption = 'ARE YOU SURE?',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Click to disband the crew.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'capn_renounce',
|
||||
type = 'button',
|
||||
caption = 'Renounce Captainhood',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'You will no longer be captain, and the role will be passed around until a crewmember takes it.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'capn_pass',
|
||||
type = 'button',
|
||||
caption = 'Pass Captain To',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Make the selected crewmember into the Captain.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'capn_plank',
|
||||
type = 'button',
|
||||
caption = 'Plank (Make Spectator)',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'The player will be returned to the lobby and can\'t join your crew for a while.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'line',
|
||||
type = 'line',
|
||||
})
|
||||
flow3.style.width = 50
|
||||
flow3.style.left_margin = 20
|
||||
flow3.style.top_margin = 4
|
||||
flow3.style.bottom_margin = 4
|
||||
|
||||
-- flow3 = flow2.add({
|
||||
-- name = 'capn_undock_normal',
|
||||
-- type = 'button',
|
||||
-- caption = 'Undock Boat',
|
||||
-- })
|
||||
-- flow3.style.minimal_width = 95
|
||||
-- flow3.style.font = 'default-bold'
|
||||
-- flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'make_officer',
|
||||
type = 'button',
|
||||
caption = 'Make Officer',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Make this player an Officer.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'unmake_officer',
|
||||
type = 'button',
|
||||
caption = 'Unamake Officer',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Remove this player as an Officer.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'revoke_class',
|
||||
type = 'button',
|
||||
caption = 'Revoke Class',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Put this player\'s class back in the Spare Classes pool.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'capn_summon_crew',
|
||||
type = 'button',
|
||||
caption = 'Summon Crew to Ship',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Teleport crewmembers to the ship.'
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'capn_requisition',
|
||||
type = 'button',
|
||||
caption = 'Requisition Items',
|
||||
})
|
||||
flow3.style.minimal_width = 95
|
||||
flow3.style.font = 'default-bold'
|
||||
flow3.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow3.tooltip = 'Take doubloons and uranium-235 from each non-officer.'
|
||||
|
||||
|
||||
flow2 = flow.add({
|
||||
name = 'undock_tip',
|
||||
type = 'label',
|
||||
})
|
||||
flow2.style.left_margin = 5
|
||||
flow2.style.top_margin = -8
|
||||
flow2.style.bottom_margin = 7
|
||||
flow2.style.single_line = false
|
||||
flow2.style.maximal_width = 190
|
||||
flow2.style.font = 'default'
|
||||
flow2.caption = 'To undock, use the top toolbar.'
|
||||
|
||||
--
|
||||
|
||||
GuiCommon.flow_add_close_button(flow, window_name .. '_piratebutton')
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- function Public.regular_update(player)
|
||||
|
||||
-- end
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
|
||||
if not player.gui.screen[window_name .. '_piratewindow'] then return end
|
||||
local flow = player.gui.screen[window_name .. '_piratewindow']
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local playercrew_status = GuiCommon.crew_overall_state_bools(player.index)
|
||||
-- local destination = Common.current_destination()
|
||||
|
||||
|
||||
--*** WHAT TO SHOW ***--
|
||||
|
||||
flow.difficulty_vote.visible = memory.overworldx and memory.overworldx == 0
|
||||
|
||||
flow.members.body.class_renounce.visible = memory.classes_table and memory.classes_table[player.index]
|
||||
|
||||
flow.members.body.officer_resign.visible = memory.officers_table and memory.officers_table[player.index]
|
||||
|
||||
flow.spare_classes.visible = memory.spare_classes and #memory.spare_classes > 0
|
||||
|
||||
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 any_class_button = false
|
||||
for _, c in pairs(Classes.Class_List) do
|
||||
if memory.spare_classes and Utils.contains(memory.spare_classes, c) and (not (player.controller_type == defines.controllers.spectator)) then
|
||||
if Common.is_captain(player) and memory.crewplayerindices and #memory.crewplayerindices > 1 then
|
||||
if other_player_selected and (not (memory.classes_table[tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])])) then
|
||||
flow.spare_classes.body.assign_flow['selfassign_class_' .. c].visible = false
|
||||
flow.spare_classes.body.assign_flow['assign_class_' .. c].visible = true
|
||||
any_class_button = true
|
||||
else
|
||||
flow.spare_classes.body.assign_flow['assign_class_' .. c].visible = false
|
||||
if (not memory.classes_table[player.index]) then
|
||||
flow.spare_classes.body.assign_flow['selfassign_class_' .. c].visible = true
|
||||
any_class_button = true
|
||||
else
|
||||
flow.spare_classes.body.assign_flow['selfassign_class_' .. c].visible = false
|
||||
end
|
||||
end
|
||||
else
|
||||
flow.spare_classes.body.assign_flow['assign_class_' .. c].visible = false
|
||||
if (not memory.classes_table[player.index]) then
|
||||
flow.spare_classes.body.assign_flow['selfassign_class_' .. c].visible = true
|
||||
any_class_button = true
|
||||
else
|
||||
flow.spare_classes.body.assign_flow['selfassign_class_' .. c].visible = false
|
||||
end
|
||||
end
|
||||
else
|
||||
flow.spare_classes.body.assign_flow['assign_class_' .. c].visible = false
|
||||
flow.spare_classes.body.assign_flow['selfassign_class_' .. c].visible = false
|
||||
end
|
||||
end
|
||||
flow.spare_classes.body.assign_flow.visible = any_class_button
|
||||
|
||||
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.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.revoke_class.visible = other_player_selected and (memory.classes_table[tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])])
|
||||
|
||||
-- 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))
|
||||
|
||||
flow.captain.body.capn_summon_crew.visible = false
|
||||
flow.captain.body.capn_requisition.visible = true
|
||||
-- flow.captain.body.capn_summon_crew.visible = memory.boat and memory.boat.state and (memory.boat.state == Boats.enum_state.RETREATING or memory.boat.state == Boats.enum_state.LEAVING_DOCK)
|
||||
|
||||
flow.captain.body.capn_disband_are_you_sure.visible = memory.disband_are_you_sure_ticks and memory.disband_are_you_sure_ticks[player.index] and memory.disband_are_you_sure_ticks[player.index] > game.tick - 60*2
|
||||
flow.captain.body.capn_disband_crew.visible = not flow.captain.body.capn_disband_are_you_sure.visible
|
||||
|
||||
flow.members.visible = true
|
||||
flow.spectators.visible = (#memory.spectatorplayerindices > 0)
|
||||
-- flow.crew_age.visible = true
|
||||
-- -- flow.crew_age.visible = memory.mode and memory.mode == 'speedrun'
|
||||
-- flow.crew_difficulty.visible = true
|
||||
|
||||
local count = 0
|
||||
if playercrew_status.spectating then
|
||||
for _, v in pairs(memory.crewplayerindices) do
|
||||
if Common.validate_player(game.players[v]) then count = count + 1 end
|
||||
end
|
||||
end
|
||||
flow.membership_buttons.spectator_join_crew.visible = playercrew_status.spectating and (not (count >= memory.capacity))
|
||||
|
||||
flow.membership_buttons.leave_crew.visible = playercrew_status.adventuring
|
||||
-- flow.membership_buttons.crewmember_join_spectators.visible = playercrew_status.adventuring
|
||||
flow.membership_buttons.crewmember_join_spectators.visible = false --disabled spectators for now... might not play well with maze world
|
||||
flow.membership_buttons.leave_spectators.visible = playercrew_status.spectating
|
||||
|
||||
flow.membership_buttons.spectator_join_crew.visible = flow.membership_buttons.spectator_join_crew.visible and (not (memory.tempbanned_from_joining_data[player.index] and game.tick < memory.tempbanned_from_joining_data[player.index] + Common.ban_from_rejoining_crew_ticks))
|
||||
|
||||
|
||||
|
||||
--== UPDATE CONTENT ==--
|
||||
|
||||
if memory.id then
|
||||
flow.caption = memory.name
|
||||
|
||||
flow.crew_age.caption = 'Age: ' .. Utils.time_mediumform((memory.age or 0)/60)
|
||||
-- flow.crew_difficulty.caption = 'Difficulty: ' .. CoreData.difficulty_options[memory.difficulty_option].text
|
||||
flow.crew_capacity_and_difficulty.caption = CoreData.difficulty_options[memory.difficulty_option].text .. ', Capacity ' .. CoreData.capacity_options[memory.capacity_option].text
|
||||
|
||||
if flow.spare_classes.visible then
|
||||
local str = ''
|
||||
|
||||
for i, c in ipairs(memory.spare_classes) do
|
||||
if i>1 then str = str .. ', ' end
|
||||
str = str .. Classes.display_form[c]
|
||||
end
|
||||
str = str .. '.'
|
||||
|
||||
flow.spare_classes.body.list.caption = str
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if flow.members.visible then
|
||||
local wrappedcrew = {}
|
||||
for _, index in pairs(memory.crewplayerindices) do
|
||||
local player2 = game.players[index]
|
||||
local tag_text = Roles.tag_text(player2)
|
||||
|
||||
wrappedcrew[#wrappedcrew + 1] = {'pirates.crewmember_displayform', index, player2.color.r, player2.color.g, player2.color.b, player2.name, tag_text}
|
||||
end
|
||||
GuiCommon.update_listbox(flow.members.body.members_listbox, wrappedcrew)
|
||||
|
||||
flow.members.header.caption = 'Crew Members (' .. (#memory.crewplayerindices or 0) .. ')'
|
||||
end
|
||||
|
||||
if flow.spectators.visible then
|
||||
local wrappedspectators = {}
|
||||
for _, index in pairs(memory.spectatorplayerindices) do
|
||||
local player2 = game.players[index]
|
||||
|
||||
wrappedspectators[#wrappedspectators + 1] = {'pirates.crewmember_displayform', index, player2.color.r, player2.color.g, player2.color.b, player2.name, ''}
|
||||
end
|
||||
GuiCommon.update_listbox(flow.spectators.body.spectators_listbox, wrappedspectators)
|
||||
end
|
||||
|
||||
-- if flow.captain.body.capn_undock_normal.visible then
|
||||
-- flow.captain.body.capn_undock_normal.enabled = ((memory.boat.state == Boats.enum_state.LANDED) and Common.query_can_pay_cost_to_leave()) or (memory.boat.state == Boats.enum_state.DOCKED)
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
function Public.click(event)
|
||||
|
||||
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 memory = Memory.get_crew_memory()
|
||||
|
||||
|
||||
if eventname == 'crewmember_join_spectators' then
|
||||
Crew.join_spectators(player, memory.id)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'leave_spectators' then
|
||||
Crew.leave_spectators(player)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'spectator_join_crew' then
|
||||
Crew.join_crew(player, memory.id)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'leave_crew' then
|
||||
Crew.leave_crew(player, true)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
-- if eventname == 'promote_officer' then
|
||||
-- Roles.promote_to_officer(player)
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- if eventname == 'demote_officer' then
|
||||
-- Roles.demote_to_officer(player)
|
||||
-- return
|
||||
-- end
|
||||
|
||||
|
||||
if string.sub(eventname, 1, 13) and string.sub(eventname, 1, 13) == 'assign_class_' then
|
||||
local other_id = tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])
|
||||
Classes.assign_class(other_id, tonumber(string.sub(eventname, 14, -1)))
|
||||
return
|
||||
end
|
||||
|
||||
if string.sub(eventname, 1, 17) and string.sub(eventname, 1, 17) == 'selfassign_class_' then
|
||||
Classes.assign_class(player.index, tonumber(string.sub(eventname, 18, -1)), true)
|
||||
return
|
||||
end
|
||||
|
||||
if string.sub(eventname, 1, 18) and string.sub(eventname, 1, 18) == 'difficulty_option_' then
|
||||
Crew.difficulty_vote(player.index, tonumber(string.sub(eventname, 19, -1)))
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if eventname == 'capn_summon_crew' then
|
||||
--double check:
|
||||
if Roles.player_privilege_level(player) >= Roles.privilege_levels.CAPTAIN then
|
||||
Crew.summon_crew()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'capn_requisition' then
|
||||
--double check:
|
||||
if Roles.player_privilege_level(player) >= Roles.privilege_levels.CAPTAIN then
|
||||
Roles.captain_requisition(memory.playerindex_captain)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'class_renounce' then
|
||||
Classes.try_renounce_class(player, true)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'capn_renounce' then
|
||||
Roles.renounce_captainhood(player)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'officer_resign' then
|
||||
Roles.resign_as_officer(player)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'capn_disband_crew' then
|
||||
--double check:
|
||||
if Roles.player_privilege_level(player) >= Roles.privilege_levels.CAPTAIN then
|
||||
if not memory.disband_are_you_sure_ticks then memory.disband_are_you_sure_ticks = {} end
|
||||
memory.disband_are_you_sure_ticks[player.index] = game.tick
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'capn_disband_are_you_sure' then
|
||||
--double check:
|
||||
if Roles.player_privilege_level(player) >= Roles.privilege_levels.CAPTAIN then
|
||||
local force = memory.force
|
||||
if force and force.valid then
|
||||
local message = player.name .. ' disbanded ' .. memory.name .. ', after ' .. Utils.time_longform((memory.real_age or 0)/60) .. '.'
|
||||
Common.notify_game(message)
|
||||
Server.to_discord_embed_raw(CoreData.comfy_emojis.trashbin .. '[' .. memory.name .. '] ' .. message)
|
||||
end
|
||||
Crew.disband_crew(true)
|
||||
end
|
||||
return
|
||||
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])
|
||||
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])
|
||||
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])
|
||||
Roles.unmake_officer(player, game.players[other_id])
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'revoke_class' then
|
||||
local other_id = tonumber(flow.members.body.members_listbox.get_item(flow.members.body.members_listbox.selected_index)[2])
|
||||
Roles.revoke_class(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])
|
||||
|
||||
Crew.plank(player, game.players[other_id])
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return Public
|
144
maps/pirates/gui/evo.lua
Normal file
144
maps/pirates/gui/evo.lua
Normal file
@ -0,0 +1,144 @@
|
||||
|
||||
local Common = require 'maps.pirates.common'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Kraken = require 'maps.pirates.surfaces.sea.kraken'
|
||||
local Public = {}
|
||||
|
||||
-- local GuiCommon = require 'maps.pirates.gui.common'
|
||||
|
||||
-- local button_sprites = {
|
||||
-- ['small-biter'] = 0,
|
||||
-- ['medium-biter'] = 0.2,
|
||||
-- ['small-spitter'] = 0.25,
|
||||
-- ['medium-spitter'] = 0.4,
|
||||
-- ['big-spitter'] = 0.5,
|
||||
-- ['big-biter'] = 0.501,
|
||||
-- ['behemoth-spitter'] = 0.9,
|
||||
-- ['behemoth-biter'] = 0.901
|
||||
-- }
|
||||
|
||||
-- local function get_alien_name(evolution_factor)
|
||||
-- local last_match = 'fish'
|
||||
-- for name, alien_threshold in pairs(button_sprites) do
|
||||
-- if evolution_factor == alien_threshold then
|
||||
-- return name
|
||||
-- end
|
||||
|
||||
-- -- next alien evolution_factor isn't reached
|
||||
-- if alien_threshold > evolution_factor then
|
||||
-- return last_match
|
||||
-- end
|
||||
|
||||
-- -- surpassed this alien evolution_factor
|
||||
-- if alien_threshold < evolution_factor then
|
||||
-- last_match = name
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- return last_match
|
||||
-- end
|
||||
|
||||
|
||||
|
||||
-- function Public.regular_update(player)
|
||||
|
||||
-- end
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local pirates_flow = player.gui.top
|
||||
|
||||
local button = pirates_flow.evo_piratebutton_frame.evo_piratebutton
|
||||
if button and button.valid then
|
||||
local evo = memory.evolution_factor or 0
|
||||
-- local evo = Math.floor(evo * 1000) * 0.001
|
||||
-- local current_alien = get_alien_name(evolution_factor)
|
||||
-- local sprite = 'entity/' .. current_alien
|
||||
|
||||
-- if evolution_factor == 0 or (memory.boat and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP)) then
|
||||
-- button.number = 0
|
||||
-- button.tooltip = 'Local biter evolution\n\n0'
|
||||
-- else
|
||||
|
||||
local destination = Common.current_destination()
|
||||
|
||||
local evolution_leagues
|
||||
local evolution_kraken
|
||||
local evolution_time
|
||||
local evolution_silo
|
||||
local evolution_nests
|
||||
local evolution_sandwurms
|
||||
local evolution_total
|
||||
|
||||
local types = {'leagues', 'kraken', 'time', 'silo', 'nests', 'sandwurms'}
|
||||
|
||||
local str = 'Local biter evolution\n\n'
|
||||
|
||||
if memory.boat and memory.boat.state and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP) then
|
||||
evolution_leagues = evo - (memory.kraken_evo or 0)
|
||||
local krakens = false
|
||||
if memory.active_sea_enemies and memory.active_sea_enemies.krakens then
|
||||
for i = 1, Kraken.kraken_slots do
|
||||
if memory.active_sea_enemies.krakens[i] then krakens = true break end
|
||||
end
|
||||
end
|
||||
if krakens then
|
||||
evolution_kraken = Balance.kraken_spawns_base_extra_evo + (memory.kraken_evo or 0)
|
||||
evolution_total = evolution_leagues + Balance.kraken_spawns_base_extra_evo
|
||||
else
|
||||
evolution_total = evolution_leagues
|
||||
end
|
||||
else
|
||||
if destination and destination.dynamic_data then
|
||||
evolution_leagues = destination.dynamic_data.evolution_accrued_leagues
|
||||
evolution_time = destination.dynamic_data.evolution_accrued_time
|
||||
evolution_nests = destination.dynamic_data.evolution_accrued_nests
|
||||
evolution_silo = destination.dynamic_data.evolution_accrued_silo
|
||||
evolution_sandwurms = destination.dynamic_data.evolution_accrued_sandwurms
|
||||
end
|
||||
evolution_total = (evolution_leagues or 0) + (evolution_time or 0) + (evolution_nests or 0) + (evolution_silo or 0) + (evolution_sandwurms or 0)
|
||||
end
|
||||
|
||||
for _, type in ipairs(types) do
|
||||
if type == 'leagues' then
|
||||
if evolution_leagues then
|
||||
str = str .. string.format('Leagues: %.2f\n', evolution_leagues)
|
||||
end
|
||||
elseif type == 'kraken' then
|
||||
if evolution_kraken then
|
||||
str = str .. string.format('Kraken: %.2f\n', evolution_kraken)
|
||||
end
|
||||
elseif type == 'time' then
|
||||
if evolution_time then
|
||||
str = str .. string.format('Time: %.2f\n', evolution_time)
|
||||
end
|
||||
elseif type == 'silo' then
|
||||
if evolution_silo then
|
||||
str = str .. string.format('Silo: %.2f\n', evolution_silo)
|
||||
end
|
||||
elseif type == 'nests' then
|
||||
if evolution_nests then
|
||||
str = str .. string.format('Nests: %.2f\n', evolution_nests)
|
||||
end
|
||||
elseif type == 'sandwurms' then
|
||||
if evolution_sandwurms then
|
||||
str = str .. string.format('Sandwurms: %.2f\n', evolution_sandwurms)
|
||||
end
|
||||
end
|
||||
end
|
||||
str = str .. string.format('Total: %.2f', evolution_total)
|
||||
|
||||
button.number = evolution_total
|
||||
button.tooltip = str
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
192
maps/pirates/gui/fuel.lua
Normal file
192
maps/pirates/gui/fuel.lua
Normal file
@ -0,0 +1,192 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local CoreData = require 'maps.pirates.coredata'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
-- local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
local Roles = require 'maps.pirates.roles.roles'
|
||||
local Crew = require 'maps.pirates.crew'
|
||||
local Shop = require 'maps.pirates.shop.shop'
|
||||
-- local Progression = require 'maps.pirates.progression'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
-- local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local GuiCommon = require 'maps.pirates.gui.common'
|
||||
local Public = {}
|
||||
|
||||
local window_name = 'fuel'
|
||||
|
||||
function Public.toggle_window(player)
|
||||
local flow, flow2, flow3
|
||||
|
||||
local shop_data_1 = Shop.Captains.main_shop_data_1
|
||||
local shop_data_2 = Shop.Captains.main_shop_data_2
|
||||
|
||||
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 = 'Captain\'s Store'
|
||||
|
||||
|
||||
flow2 = flow.add({
|
||||
name = 'trades',
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow2.style.top_margin = 3
|
||||
flow2.style.bottom_margin = 3
|
||||
flow2.style.horizontal_align = 'center'
|
||||
flow2.style.vertical_align = 'center'
|
||||
|
||||
for k, _ in pairs(shop_data_1) do
|
||||
GuiCommon.flow_add_shop_item(flow2, k)
|
||||
end
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'line_1',
|
||||
type = 'line',
|
||||
})
|
||||
flow3.style.width = 100
|
||||
|
||||
for k, _ in pairs(shop_data_2) do
|
||||
GuiCommon.flow_add_shop_item(flow2, k)
|
||||
end
|
||||
|
||||
|
||||
flow2 = GuiCommon.flow_add_close_button(flow, window_name .. '_piratebutton')
|
||||
|
||||
flow2.add({
|
||||
name = 'tospend',
|
||||
type = 'sprite-button',
|
||||
sprite = 'item/coin',
|
||||
index = 1,
|
||||
enabled = false,
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
function Public.regular_update(player)
|
||||
local flow
|
||||
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
if not player.gui.screen[window_name .. '_piratewindow'] then return end
|
||||
flow = player.gui.screen[window_name .. '_piratewindow']
|
||||
|
||||
if Roles.player_privilege_level(player) >= Roles.privilege_levels.OFFICER then
|
||||
flow.close_button_flow.hflow.tospend.visible = true
|
||||
|
||||
local inv = player.get_inventory(defines.inventory.character_main)
|
||||
if inv and inv.valid then
|
||||
local coin_amount = inv.get_item_count('coin') or 0
|
||||
|
||||
flow.close_button_flow.hflow.tospend.number = coin_amount
|
||||
flow.close_button_flow.hflow.tospend.tooltip = string.format("You're holding " .. Utils.bignumber_abbrevform2(coin_amount) .. " doubloons.")
|
||||
end
|
||||
else
|
||||
flow.close_button_flow.hflow.tospend.visible = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
|
||||
local flow
|
||||
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local shop_data = Utils.nonrepeating_join_dict(Shop.Captains.main_shop_data_1, Shop.Captains.main_shop_data_2)
|
||||
local shop_data_1 = Shop.Captains.main_shop_data_1
|
||||
local shop_data_2 = Shop.Captains.main_shop_data_2
|
||||
|
||||
local availability_data = memory.mainshop_availability_bools
|
||||
|
||||
if not player.gui.screen[window_name .. '_piratewindow'] then return end
|
||||
flow = player.gui.screen[window_name .. '_piratewindow']
|
||||
|
||||
|
||||
--*** WHAT TO SHOW ***--
|
||||
|
||||
-- if memory.stored_fuel then
|
||||
-- flow.close_button_flow.hflow.tospend.number = memory.stored_fuel
|
||||
-- flow.close_button_flow.hflow.tospend.tooltip = string.format('The crew has %01d stored coal.', memory.stored_fuel)
|
||||
-- else
|
||||
-- flow.close_button_flow.hflow.tospend.number = 0
|
||||
-- flow.close_button_flow.hflow.tospend.tooltip = string.format('The crew has %01d stored coal.', 0)
|
||||
-- end
|
||||
|
||||
|
||||
|
||||
if memory.crewstatus == Crew.enum.ADVENTURING then
|
||||
flow.trades.visible = true
|
||||
else
|
||||
flow.trades.visible = false
|
||||
end
|
||||
|
||||
local anything_in_shop_1 = false
|
||||
for k, _ in pairs(shop_data_1) do
|
||||
if availability_data and availability_data[k] == true then
|
||||
flow.trades[k].visible = true
|
||||
anything_in_shop_1 = true
|
||||
if Roles.player_privilege_level(player) >= Roles.privilege_levels.OFFICER then
|
||||
flow.trades[k].buy_button.visible = true
|
||||
else
|
||||
flow.trades[k].buy_button.visible = false
|
||||
end
|
||||
else
|
||||
flow.trades[k].visible = false
|
||||
end
|
||||
end
|
||||
flow.trades.line_1.visible = anything_in_shop_1
|
||||
for k, _ in pairs(shop_data_2) do
|
||||
if availability_data and availability_data[k] == true then
|
||||
flow.trades[k].visible = true
|
||||
if Roles.player_privilege_level(player) >= Roles.privilege_levels.OFFICER then
|
||||
flow.trades[k].buy_button.visible = true
|
||||
else
|
||||
flow.trades[k].buy_button.visible = false
|
||||
end
|
||||
else
|
||||
flow.trades[k].visible = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--*** UPDATE CONTENT ***--
|
||||
|
||||
local multiplier = Balance.main_shop_cost_multiplier()
|
||||
|
||||
for k, v in pairs(shop_data) do
|
||||
for k2, v2 in pairs(v.base_cost) do
|
||||
if v2 == false then
|
||||
flow.trades[k]['cost_' .. k2].number = nil
|
||||
else
|
||||
flow.trades[k]['cost_' .. k2].number = multiplier * v2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function Public.click(event)
|
||||
|
||||
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 memory = Memory.get_crew_memory()
|
||||
|
||||
if eventname == 'buy_button' then
|
||||
Shop.Captains.main_shop_try_purchase(player, event.element.parent.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return Public
|
1174
maps/pirates/gui/gui.lua
Normal file
1174
maps/pirates/gui/gui.lua
Normal file
File diff suppressed because it is too large
Load Diff
236
maps/pirates/gui/info.lua
Normal file
236
maps/pirates/gui/info.lua
Normal file
@ -0,0 +1,236 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
-- local Lobby = require 'maps.pirates.surfaces.lobby'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
-- local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local GuiCommon = require 'maps.pirates.gui.common'
|
||||
local Public = {}
|
||||
|
||||
|
||||
local window_name = 'info'
|
||||
|
||||
|
||||
local width = 430
|
||||
|
||||
|
||||
|
||||
function Public.toggle_window(player)
|
||||
local flow, flow2, flow3, flow4
|
||||
|
||||
if player.gui.screen[window_name .. '_piratewindow'] then player.gui.screen[window_name .. '_piratewindow'].destroy() return end
|
||||
|
||||
flow = player.gui.screen.add{
|
||||
type = 'tabbed-pane',
|
||||
name = window_name .. '_piratewindow',
|
||||
direction = 'vertical'
|
||||
}
|
||||
flow.location = {x = 90, y = 90}
|
||||
flow.selected_tab_index = 1
|
||||
|
||||
flow.style = 'frame_tabbed_pane'
|
||||
flow.style.width = width
|
||||
flow.style.height = 420
|
||||
|
||||
flow2 = Public.flow_add_info_tab(flow, 'Info')
|
||||
|
||||
flow3 = flow2.parent.last_info_flow_1.last_info_flow_2
|
||||
flow4 = flow3.add{type = "label", caption = {"pirates.softmod_info_body_1"}}
|
||||
flow4.style.font_color = GuiCommon.friendly_font_color
|
||||
flow4.style.single_line = false
|
||||
flow4.style.font = 'debug'
|
||||
flow4.style.top_margin = -2
|
||||
flow4.style.bottom_margin = 0
|
||||
-- flow4.style.bottom_margin = 16
|
||||
|
||||
Public.flow_add_info_sections(flow2, {'game_description'})
|
||||
|
||||
flow2 = Public.flow_add_info_tab(flow, 'Updates')
|
||||
|
||||
Public.flow_add_info_sections(flow2, {'updates', 'bugs'})
|
||||
|
||||
flow2 = Public.flow_add_info_tab(flow, 'Tips')
|
||||
|
||||
Public.flow_add_info_sections(flow2, {'new_players', 'tips'})
|
||||
|
||||
flow2 = Public.flow_add_info_tab(flow, 'Credits')
|
||||
|
||||
Public.flow_add_info_sections(flow2, {'credits'})
|
||||
end
|
||||
|
||||
|
||||
function Public.flow_add_info_sections(flow, sections_list)
|
||||
local flow2
|
||||
|
||||
for j = 1, #sections_list do
|
||||
local i = sections_list[j]
|
||||
|
||||
flow2 = flow.add{type = "label", caption = {"pirates.softmod_info_" .. i .. "_1"}}
|
||||
flow2.style.font_color = GuiCommon.friendly_font_color
|
||||
flow2.style.single_line = false
|
||||
flow2.style.font = 'heading-3'
|
||||
flow2.style.bottom_margin = -4
|
||||
|
||||
flow2 = flow.add{type = "label", caption = {"pirates.softmod_info_" .. i .. "_2"}}
|
||||
flow2.style.font_color = GuiCommon.friendly_font_color
|
||||
flow2.style.single_line = false
|
||||
flow2.style.font = 'default'
|
||||
flow2.style.bottom_margin = 12
|
||||
flow2.style.left_margin = 8
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.flow_add_info_tab(flow, tab_name)
|
||||
|
||||
local tab, contents, ret, flow3, flow4, flow5
|
||||
|
||||
tab = flow.add{type='tab', caption=tab_name}
|
||||
tab.style = 'frame_tab'
|
||||
|
||||
contents = flow.add({
|
||||
type = 'frame',
|
||||
direction = 'vertical',
|
||||
})
|
||||
contents.style.vertically_stretchable = true
|
||||
contents.style.width = width
|
||||
contents.style.natural_height = 2000
|
||||
contents.style.top_margin = -8
|
||||
contents.style.bottom_margin = -12
|
||||
contents.style.left_margin = -7
|
||||
contents.style.right_margin = -11
|
||||
|
||||
flow3 = contents.add({
|
||||
type = 'flow',
|
||||
name = 'header_flow_1',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
flow3.style.horizontally_stretchable = true
|
||||
flow3.style.horizontal_align = 'center'
|
||||
|
||||
flow4 = flow3.add({
|
||||
type = 'flow',
|
||||
name = 'header_flow_2',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow4.style.horizontally_stretchable = true
|
||||
flow4.style.horizontal_align = 'center'
|
||||
|
||||
flow5 = flow4.add{type = "label", caption = {"", {"pirates.softmod_info_header_before_version_number"}, CoreData.version_string, {"pirates.softmod_info_header_after_version_number"}}}
|
||||
flow5.style.font_color = GuiCommon.friendly_font_color
|
||||
flow5.style.font = 'heading-1'
|
||||
flow5.style.bottom_margin = 2
|
||||
|
||||
flow5 = flow4.add{type = "label", caption = {"pirates.softmod_info_body_promote"}}
|
||||
flow5.style.font_color = GuiCommon.friendly_font_color
|
||||
flow5.style.single_line = false
|
||||
flow5.style.font = 'default-small'
|
||||
flow5.style.top_margin = -12
|
||||
flow5.style.bottom_margin = 8
|
||||
|
||||
ret = contents.add({
|
||||
type = 'flow',
|
||||
name = 'main_flow_1',
|
||||
direction = 'vertical',
|
||||
})
|
||||
ret.style.horizontally_stretchable = true
|
||||
|
||||
flow3 = contents.add({
|
||||
type = 'flow',
|
||||
name = 'last_info_flow_1',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
flow3.style.horizontally_stretchable = true
|
||||
flow3.style.horizontal_align = 'center'
|
||||
|
||||
flow4 = flow3.add({
|
||||
type = 'flow',
|
||||
name = 'last_info_flow_2',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow4.style.horizontally_stretchable = true
|
||||
flow4.style.horizontal_align = 'center'
|
||||
|
||||
flow3 = contents.add({
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow3.style.vertically_stretchable = true
|
||||
flow3.style.horizontally_stretchable = true
|
||||
|
||||
flow3 = contents.add({
|
||||
type = 'flow',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
flow3.style.horizontally_stretchable = true
|
||||
flow3.style.horizontal_align = 'center'
|
||||
|
||||
flow4 = flow3.add{type = "label", caption = {"pirates.softmod_info_body_clicky"}}
|
||||
flow4.style.font_color = GuiCommon.friendly_font_color
|
||||
flow4.style.single_line = false
|
||||
flow4.style.font = 'default'
|
||||
flow4.style.bottom_margin = 4
|
||||
flow4.style.top_margin = 3
|
||||
|
||||
flow.add_tab(tab, contents)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.click(event)
|
||||
|
||||
local player = game.players[event.element.player_index]
|
||||
-- local name = 'info'
|
||||
|
||||
local element = event.element
|
||||
local eventtype = element.type
|
||||
|
||||
if not player.gui.screen[window_name .. '_piratewindow'] then return end
|
||||
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
if eventtype ~= 'tab' and (
|
||||
element.name == (window_name .. '_piratewindow') or
|
||||
(element.parent and element.parent.name == (window_name .. '_piratewindow')) or
|
||||
(element.parent and element.parent.parent and element.parent.parent.name == (window_name .. '_piratewindow')) or
|
||||
(element.parent and element.parent.parent and element.parent.parent.parent and element.parent.parent.parent.name == (window_name .. '_piratewindow')) or
|
||||
(element.parent and element.parent.parent and element.parent.parent.parent and element.parent.parent.parent.parent and element.parent.parent.parent.parent.name == (window_name .. '_piratewindow')) or
|
||||
(element.parent and element.parent.parent and element.parent.parent.parent and element.parent.parent.parent.parent and element.parent.parent.parent.parent.parent and element.parent.parent.parent.parent.parent.name == (window_name .. '_piratewindow'))
|
||||
) then
|
||||
Public.toggle_window(player)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- function Public.regular_update(player)
|
||||
|
||||
-- end
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
|
||||
if not player.gui.screen[window_name .. '_piratewindow'] then return end
|
||||
local flow = player.gui.screen[window_name .. '_piratewindow']
|
||||
|
||||
local flow2 = flow
|
||||
-- warning, if you make these too small, it loses 'Click to dismiss.'
|
||||
if flow2.selected_tab_index == 1 then
|
||||
flow2.style.height = 400
|
||||
elseif flow2.selected_tab_index == 2 then
|
||||
flow2.style.height = 330
|
||||
elseif flow2.selected_tab_index == 3 then
|
||||
flow2.style.height = 660
|
||||
elseif flow2.selected_tab_index == 4 then
|
||||
flow2.style.height = 330
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
return Public
|
251
maps/pirates/gui/minimap.lua
Normal file
251
maps/pirates/gui/minimap.lua
Normal file
@ -0,0 +1,251 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Common = require 'maps.pirates.common'
|
||||
-- local CoreData = require 'maps.pirates.coredata'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
-- local Crew = require 'maps.pirates.crew'
|
||||
-- local Progression = require 'maps.pirates.progression'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
-- local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local GuiCommon = require 'maps.pirates.gui.common'
|
||||
local Public = {}
|
||||
|
||||
local window_name = 'minimap'
|
||||
|
||||
local default_zoom = 0.1
|
||||
local default_size = 320
|
||||
|
||||
function Public.toggle_window(player)
|
||||
local flow, flow2
|
||||
|
||||
local window = player.gui.screen[window_name .. '_piratewindow']
|
||||
if window then
|
||||
local switch_state = window.close_button_flow.hflow.switch_auto_map.switch_state
|
||||
local auto_map = true
|
||||
if switch_state == 'right' then
|
||||
auto_map = false
|
||||
end
|
||||
GuiCommon.update_gui_memory(player, window_name, 'auto_map', auto_map)
|
||||
|
||||
window.destroy()
|
||||
return
|
||||
end -- else:
|
||||
|
||||
flow = GuiCommon.new_window(player, window_name)
|
||||
flow.caption = 'Outside View'
|
||||
flow.style.maximal_width = 800
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local gui_memory = global_memory.player_gui_memories[player.index]
|
||||
|
||||
local auto_map
|
||||
if gui_memory and gui_memory[window_name] then
|
||||
auto_map = gui_memory[window_name].auto_map
|
||||
else
|
||||
auto_map = true
|
||||
end
|
||||
local switch_state = 'right'
|
||||
if auto_map then
|
||||
switch_state = 'left'
|
||||
end
|
||||
|
||||
if not (memory.boat and memory.boat.position and memory.boat.surface_name) then return end
|
||||
|
||||
local position = memory.boat.position
|
||||
local destination = Common.current_destination()
|
||||
if (destination and destination.type and destination.type == Surfaces.enum.ISLAND and destination.static_params and destination.static_params.boat_starting_xposition) then
|
||||
-- nicer viewing position:
|
||||
position = {x = destination.static_params.boat_starting_xposition + 50, y = destination.static_params.boat_starting_yposition or 0}
|
||||
end
|
||||
local zoom
|
||||
if gui_memory and gui_memory[window_name] and gui_memory[window_name].zoom then
|
||||
zoom = gui_memory[window_name].zoom
|
||||
else
|
||||
zoom = default_zoom
|
||||
end
|
||||
local size
|
||||
if gui_memory and gui_memory[window_name] and gui_memory[window_name].size then
|
||||
size = gui_memory[window_name].size
|
||||
else
|
||||
size = default_size
|
||||
end
|
||||
|
||||
local element = flow['camera']
|
||||
if not element then
|
||||
element =
|
||||
flow.add(
|
||||
{
|
||||
type = 'camera',
|
||||
name = 'camera',
|
||||
position = position,
|
||||
surface_index = game.surfaces[memory.boat.surface_name].index,
|
||||
zoom = zoom,
|
||||
tooltip = 'LMB: Zoom in.\nRMB: Zoom out.\nMMB: Scale window.'
|
||||
}
|
||||
)
|
||||
element.style.margin = 1
|
||||
element.style.minimal_height = size
|
||||
element.style.minimal_width = size
|
||||
element.style.maximal_height = size
|
||||
element.style.maximal_width = size
|
||||
end
|
||||
|
||||
flow2 = GuiCommon.flow_add_close_button(flow, window_name .. '_piratebutton')
|
||||
flow2.add(
|
||||
{
|
||||
type = 'switch',
|
||||
name = 'switch_auto_map',
|
||||
index = 1,
|
||||
allow_none_state = false,
|
||||
switch_state = switch_state,
|
||||
left_label_caption = 'Auto Show Map — On',
|
||||
right_label_caption = 'Off'
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- function Public.regular_update(player)
|
||||
|
||||
-- end
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
local flow
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if not player.gui.screen[window_name .. '_piratewindow'] then return end
|
||||
flow = player.gui.screen[window_name .. '_piratewindow']
|
||||
|
||||
local element = flow['camera']
|
||||
if element then
|
||||
local position = memory.boat.position
|
||||
local destination = Common.current_destination()
|
||||
if (destination and destination.type and destination.type == Surfaces.enum.ISLAND and memory.boat.surface_name and memory.boat.surface_name == destination.surface_name and destination.static_params and destination.static_params.boat_starting_xposition) then
|
||||
-- nicer viewing position:
|
||||
position = {x = destination.static_params.boat_starting_xposition + 50, y = destination.static_params.boat_starting_yposition or 0}
|
||||
end
|
||||
|
||||
if position then
|
||||
element.position = position
|
||||
end
|
||||
if memory.boat.surface_name and game.surfaces[memory.boat.surface_name] and game.surfaces[memory.boat.surface_name].valid then
|
||||
element.surface_index = game.surfaces[memory.boat.surface_name].index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.click(event)
|
||||
|
||||
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 memory = Memory.get_crew_memory()
|
||||
-- local shop_data = Shop.main_shop_data
|
||||
|
||||
-- if eventname == 'buy_button' then
|
||||
-- Shop.Captains.main_shop_try_purchase(event.element.parent.name)
|
||||
-- end
|
||||
|
||||
if eventname ~= 'camera' then return end
|
||||
|
||||
local zoom = default_zoom
|
||||
local size = default_size
|
||||
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local gui_memory = global_memory.player_gui_memories[player.index]
|
||||
|
||||
if gui_memory and gui_memory[window_name] then
|
||||
zoom = gui_memory[window_name].zoom or default_zoom
|
||||
size = gui_memory[window_name].size or default_size
|
||||
end
|
||||
|
||||
if event.button == defines.mouse_button_type.right then
|
||||
if zoom == 0.15 then
|
||||
zoom = 0.11
|
||||
elseif zoom == 0.11 then
|
||||
zoom = 0.07
|
||||
else
|
||||
zoom = 0.04
|
||||
end
|
||||
event.element.zoom = zoom
|
||||
end
|
||||
if event.button == defines.mouse_button_type.left then
|
||||
if zoom == 0.04 then
|
||||
zoom = 0.07
|
||||
elseif zoom == 0.07 then
|
||||
zoom = 0.11
|
||||
else
|
||||
zoom = 0.15
|
||||
end
|
||||
event.element.zoom = zoom
|
||||
end
|
||||
if event.button == defines.mouse_button_type.middle then
|
||||
if size == 340 then
|
||||
size = 440
|
||||
elseif size == 440 then
|
||||
size = 560
|
||||
elseif size == 560 then
|
||||
size = 700
|
||||
elseif size == 700 then
|
||||
size = 280
|
||||
else
|
||||
size = 340
|
||||
end
|
||||
event.element.style.minimal_height = size
|
||||
event.element.style.minimal_width = size
|
||||
event.element.style.maximal_height = size
|
||||
event.element.style.maximal_width = size
|
||||
end
|
||||
|
||||
GuiCommon.update_gui_memory(player, window_name, 'zoom', zoom)
|
||||
GuiCommon.update_gui_memory(player, window_name, 'size', size)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function on_player_changed_surface(event)
|
||||
local player = game.players[event.player_index]
|
||||
if not Common.validate_player_and_character(player) then
|
||||
return
|
||||
end
|
||||
|
||||
local window = player.gui.screen[window_name .. '_piratewindow']
|
||||
|
||||
local from_hold_bool = string.sub(game.surfaces[event.surface_index].name, 9, 12) == 'Hold'
|
||||
local to_hold_bool = string.sub(player.surface.name, 9, 12) == 'Hold'
|
||||
|
||||
if from_hold_bool and (not to_hold_bool) then
|
||||
if window then
|
||||
Public.toggle_window(player)
|
||||
end
|
||||
elseif to_hold_bool and (not from_hold_bool) then
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local gui_memory = global_memory.player_gui_memories[player.index]
|
||||
|
||||
if (gui_memory and gui_memory[window_name] and gui_memory[window_name].auto_map) or (not gui_memory) or (gui_memory and (not gui_memory[window_name])) then --if no gui memory exists for this, default to opening the minimap
|
||||
Public.toggle_window(player)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.add(defines.events.on_player_changed_surface, on_player_changed_surface)
|
||||
|
||||
return Public
|
175
maps/pirates/gui/progress.lua
Normal file
175
maps/pirates/gui/progress.lua
Normal file
@ -0,0 +1,175 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
local Lobby = require 'maps.pirates.surfaces.lobby'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
-- local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local GuiCommon = require 'maps.pirates.gui.common'
|
||||
local Public = {}
|
||||
|
||||
|
||||
local window_name = 'progress'
|
||||
|
||||
function Public.toggle_window(player)
|
||||
|
||||
if player.gui.screen[window_name .. '_piratewindow'] then player.gui.screen[window_name .. '_piratewindow'].destroy() return end
|
||||
|
||||
local flow, flow2, flow3
|
||||
flow = GuiCommon.new_window(player, window_name)
|
||||
flow.caption = 'Progress'
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'distance_travelled', 'Distance Travelled:')
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'leagues',
|
||||
type = 'label',
|
||||
})
|
||||
flow3.style.left_margin = 5
|
||||
flow3.style.top_margin = -3
|
||||
flow3.style.bottom_margin = -3
|
||||
flow3.style.single_line = false
|
||||
flow3.style.maximal_width = 160
|
||||
flow3.style.font = 'default-dropdown'
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'current_location', 'Current location: ')
|
||||
|
||||
-- flow3 = flow2.add({
|
||||
-- name = 'location_name',
|
||||
-- type = 'label',
|
||||
-- })
|
||||
-- flow3.style.left_margin = 5
|
||||
-- flow3.style.top_margin = -3
|
||||
-- flow3.style.bottom_margin = -3
|
||||
-- flow3.style.single_line = false
|
||||
-- flow3.style.maximal_width = 160
|
||||
-- flow3.style.font = 'default-dropdown'
|
||||
|
||||
-- flow3 = flow2.add({type = 'label', name = 'hidden_ores_yes', caption = 'Ores detected:'})
|
||||
|
||||
-- flow3 = flow2.add({type = 'table', name = 'hidden_ores_yes_table', column_count = 3})
|
||||
-- flow3.style.left_margin = 5
|
||||
-- flow3.style.bottom_margin = 4
|
||||
|
||||
-- for _, ore in ipairs(CoreData.ore_types) do
|
||||
-- flow3.add({type = 'sprite-button', name = ore.name, sprite = ore.sprite_name, enabled = false, number = 0})
|
||||
-- end
|
||||
|
||||
-- flow3 = flow2.add({type = 'label', name = 'hidden_ores_no', caption = 'Ores detected: None'})
|
||||
|
||||
-- -- flow3 = flow2.add({type = 'label', name = 'daynight', caption = ''})
|
||||
|
||||
-- flow3 = flow2.add({type = 'label', name = 'patch_size', caption = ''})
|
||||
-- flow3.style.top_margin = -3
|
||||
|
||||
flow3 = flow2.add({type = 'label', name = 'daynight', caption = ''})
|
||||
flow3.style.top_margin = -3
|
||||
|
||||
|
||||
-- flow2 = GuiCommon.flow_add_section(flow, 'departure_items', 'Resources needed for departure:')
|
||||
|
||||
-- flow3.style.bottom_margin = -2
|
||||
-- flow3 = flow2.add({type = 'table', name = 'needed', column_count = 4})
|
||||
-- flow3.style.left_margin = 5
|
||||
-- for _, item in ipairs(CoreData.departure_items) do
|
||||
-- flow3.add({type = 'sprite-button', name = item.name, sprite = item.sprite_name, enabled = false, number = 0})
|
||||
-- end
|
||||
|
||||
GuiCommon.flow_add_close_button(flow, window_name .. '_piratebutton')
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
-- function Public.regular_update(player)
|
||||
|
||||
-- end
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
if not player.gui.screen[window_name .. '_piratewindow'] then return end
|
||||
local flow = player.gui.screen[window_name .. '_piratewindow']
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
-- local type = destination.type
|
||||
-- local subtype = destination.subtype
|
||||
|
||||
local scope = Surfaces.get_scope(destination)
|
||||
|
||||
local name
|
||||
if scope then
|
||||
name = (destination and destination.static_params and destination.static_params.name) and destination.static_params.name or scope.Data.display_name
|
||||
else
|
||||
name = Lobby.Data.display_name
|
||||
end
|
||||
|
||||
flow.current_location.header.caption = string.format('Current location: %s', name)
|
||||
flow.distance_travelled.body.leagues.caption = string.format('%d leagues', memory.overworldx or 0)
|
||||
|
||||
-- local daynighttype
|
||||
-- if destination.static_params and destination.static_params.daynightcycletype then
|
||||
-- daynighttype = destination.static_params.daynightcycletype
|
||||
-- else
|
||||
-- daynighttype = 1
|
||||
-- end
|
||||
-- flow.current_location.body.daynight.caption = string.format('Day/night cycle: %s', CoreData.daynightcycle_types[daynighttype].displayname)
|
||||
|
||||
-- if destination.static_params and destination.static_params.radius_squared_modifier then
|
||||
-- local radius_squared_modifier = destination.static_params.radius_squared_modifier
|
||||
-- flow.current_location.body.patch_size.visible = true
|
||||
-- if radius_squared_modifier <= 0.65 then
|
||||
-- flow.current_location.body.patch_size.caption = 'Patch sizing: ' .. 'Nano'
|
||||
-- elseif radius_squared_modifier <= 0.85 then
|
||||
-- flow.current_location.body.patch_size.caption = 'Patch sizing: ' .. 'Small'
|
||||
-- elseif radius_squared_modifier <= 1.5 then
|
||||
-- flow.current_location.body.patch_size.caption = 'Patch sizing: ' .. 'Normal'
|
||||
-- else
|
||||
-- flow.current_location.body.patch_size.caption = 'Patch sizing: ' .. 'Large'
|
||||
-- end
|
||||
-- else
|
||||
-- flow.current_location.body.patch_size.visible = false
|
||||
-- end
|
||||
|
||||
-- if destination.static_params and destination.static_params.daynightcycletype then
|
||||
-- flow.current_location.body.daynight.visible = true
|
||||
-- local daynightcycletype = destination.static_params.daynightcycletype
|
||||
-- flow.current_location.body.daynight.caption = 'Daynight cycle: ' .. CoreData.daynightcycle_types[daynightcycletype].displayname
|
||||
|
||||
-- else
|
||||
-- flow.current_location.body.daynight.visible = false
|
||||
-- end
|
||||
local daynightcycletype = destination.static_params.daynightcycletype or 1
|
||||
flow.current_location.body.daynight.caption = 'Time of day: ' .. CoreData.daynightcycle_types[daynightcycletype].displayname
|
||||
|
||||
|
||||
-- local ores
|
||||
-- -- if destination.static_params and destination.static_params.abstract_ore_amounts then ores = destination.static_params.abstract_ore_amounts end
|
||||
-- if destination.dynamic_data and destination.dynamic_data.hidden_ore_remaining_abstract then ores = destination.dynamic_data.hidden_ore_remaining_abstract end
|
||||
|
||||
-- if ores then
|
||||
-- flow.current_location.body.hidden_ores_yes.visible = true
|
||||
-- flow.current_location.body.hidden_ores_yes_table.visible = true
|
||||
-- flow.current_location.body.patch_size.visible = true
|
||||
-- flow.current_location.body.hidden_ores_no.visible = false
|
||||
|
||||
-- for _, ore in ipairs(CoreData.ore_types) do
|
||||
-- if ores[ore.name] then
|
||||
-- flow.current_location.body.hidden_ores_yes_table[ore.name].number = Math.ceil(ores[ore.name])
|
||||
-- else
|
||||
-- flow.current_location.body.hidden_ores_yes_table[ore.name].number = 0
|
||||
-- end
|
||||
-- end
|
||||
-- else
|
||||
-- flow.current_location.body.hidden_ores_yes.visible = false
|
||||
-- flow.current_location.body.hidden_ores_yes_table.visible = false
|
||||
-- flow.current_location.body.patch_size.visible = false
|
||||
-- flow.current_location.body.hidden_ores_no.visible = true
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
682
maps/pirates/gui/runs.lua
Normal file
682
maps/pirates/gui/runs.lua
Normal file
@ -0,0 +1,682 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
local Crew = require 'maps.pirates.crew'
|
||||
local Progression = require 'maps.pirates.progression'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local GuiCommon = require 'maps.pirates.gui.common'
|
||||
-- local Server = require 'utils.server'
|
||||
local Public = {}
|
||||
|
||||
|
||||
local window_name = 'runs'
|
||||
|
||||
|
||||
local function flow_add_proposal_slider(flow, name, displayname, indices_count, starting_index, tooltip)
|
||||
local flow2, flow3, flow4
|
||||
|
||||
|
||||
flow2 = flow.add({
|
||||
name = name,
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow2.style.horizontal_align = 'left'
|
||||
flow2.style.width = 130
|
||||
|
||||
flow3 = flow2.add({
|
||||
type = 'label',
|
||||
caption = displayname,
|
||||
})
|
||||
flow3.style.font = 'heading-3'
|
||||
flow3.style.height = 20
|
||||
flow3.style.margin = 0
|
||||
flow3.style.padding = 0
|
||||
flow3.style.top_padding = -4
|
||||
flow3.style.bottom_margin = 0
|
||||
flow3.style.font_color = GuiCommon.subsection_header_font_color
|
||||
flow3.tooltip = tooltip
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = name,
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow3.style.horizontal_align = 'center'
|
||||
flow3.style.width = 130
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'slider',
|
||||
type = 'slider',
|
||||
value_step = 1,
|
||||
minimum_value = 1,
|
||||
maximum_value = indices_count,
|
||||
value = starting_index,
|
||||
discrete_values = true,
|
||||
discrete_slider = true,
|
||||
})
|
||||
flow4.style.width = 100
|
||||
flow4.style.margin = 0
|
||||
flow4.tooltip = tooltip
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'readoff_text',
|
||||
type = 'label',
|
||||
caption = '',
|
||||
})
|
||||
flow4.style.font = 'default-listbox'
|
||||
flow4.style.height = 20
|
||||
flow4.style.margin = 0
|
||||
flow4.style.padding = 0
|
||||
flow4.style.top_padding = 0
|
||||
flow4.style.bottom_margin = 16
|
||||
flow4.tooltip = tooltip
|
||||
|
||||
flow2 = flow.add({
|
||||
name = name .. '_readoff_icon',
|
||||
type = 'sprite-button',
|
||||
enabled = false,
|
||||
})
|
||||
flow2.style.width = 48
|
||||
flow2.style.height = 48
|
||||
flow2.tooltip = tooltip
|
||||
|
||||
return flow2
|
||||
end
|
||||
|
||||
|
||||
-- commented out for luacheck:
|
||||
-- local function flow_add_proposal_switch(flow, name, displayname, starting_position, tooltip)
|
||||
-- local flow2, flow3, flow4
|
||||
|
||||
-- flow2 = flow.add({
|
||||
-- name = name,
|
||||
-- type = 'flow',
|
||||
-- direction = 'vertical',
|
||||
-- })
|
||||
-- flow2.style.horizontal_align = 'left'
|
||||
-- flow2.style.width = 130
|
||||
|
||||
-- flow3 = flow2.add({
|
||||
-- type = 'label',
|
||||
-- caption = displayname,
|
||||
-- })
|
||||
-- flow3.style.font = 'heading-3'
|
||||
-- flow3.style.height = 20
|
||||
-- flow3.style.margin = 0
|
||||
-- flow3.style.padding = 0
|
||||
-- flow3.style.top_padding = -4
|
||||
-- flow3.style.bottom_margin = 0
|
||||
-- flow3.style.font_color = GuiCommon.subsection_header_font_color
|
||||
-- flow3.tooltip = tooltip
|
||||
|
||||
-- flow3 = flow2.add({
|
||||
-- name = name,
|
||||
-- type = 'flow',
|
||||
-- direction = 'vertical',
|
||||
-- })
|
||||
-- flow3.style.horizontal_align = 'center'
|
||||
-- flow3.style.width = 130
|
||||
|
||||
-- flow4 = flow3.add({
|
||||
-- name = 'switch',
|
||||
-- type = 'switch',
|
||||
-- switch_state = starting_position,
|
||||
-- })
|
||||
-- -- flow4.style.width = 80
|
||||
-- -- flow4.style.height = 40
|
||||
-- flow4.style.margin = 0
|
||||
-- flow4.tooltip = tooltip
|
||||
|
||||
-- flow4 = flow3.add({
|
||||
-- name = 'readoff_text',
|
||||
-- type = 'label',
|
||||
-- caption = '',
|
||||
-- })
|
||||
-- flow4.style.font = 'default-listbox'
|
||||
-- flow4.style.height = 20
|
||||
-- flow4.style.margin = 0
|
||||
-- flow4.style.padding = 0
|
||||
-- flow4.style.top_padding = 0
|
||||
-- flow4.style.bottom_margin = 16
|
||||
-- flow4.tooltip = tooltip
|
||||
|
||||
-- flow2 = flow.add({
|
||||
-- name = name .. '_readoff_icon',
|
||||
-- type = 'sprite-button',
|
||||
-- enabled = false,
|
||||
-- })
|
||||
-- flow2.style.width = 48
|
||||
-- flow2.style.height = 48
|
||||
-- flow2.tooltip = tooltip
|
||||
|
||||
-- return flow2
|
||||
-- end
|
||||
|
||||
|
||||
function Public.toggle_window(player)
|
||||
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 = 'Play'
|
||||
|
||||
--*** ONGOING RUNS ***--
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'ongoing_runs', 'Ongoing Runs')
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'helpful_tip',
|
||||
type = 'label',
|
||||
caption = 'To join a run, first select it in the table below.',
|
||||
})
|
||||
flow3.style.font_color = {r=0.90, g=0.90, b=0.90}
|
||||
flow3.style.single_line = false
|
||||
flow3.style.maximal_width = 160
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'ongoing_runs_listbox',
|
||||
type = 'list-box',
|
||||
})
|
||||
flow3.style.margin = 2
|
||||
flow3.style.horizontally_stretchable = true
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'flow_buttons',
|
||||
type = 'flow',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'join_spectators',
|
||||
type = 'button',
|
||||
caption = 'Spectate',
|
||||
})
|
||||
flow4.style.minimal_width = 95
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'join_crew',
|
||||
type = 'button',
|
||||
caption = 'Join Crew',
|
||||
})
|
||||
flow4.style.minimal_width = 95
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'leave_spectators',
|
||||
type = 'button',
|
||||
caption = 'Return to Lobby',
|
||||
})
|
||||
flow4.style.minimal_width = 95
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'wait_to_join',
|
||||
type = 'label',
|
||||
})
|
||||
flow3.style.left_margin = 5
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'leaving_prompt',
|
||||
type = 'label',
|
||||
caption = 'Hop on board.',
|
||||
})
|
||||
flow3.style.left_margin = 5
|
||||
|
||||
|
||||
-- PROPOSALS --
|
||||
|
||||
flow2 = GuiCommon.flow_add_section(flow, 'proposals', 'Proposals')
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'proposals_listbox',
|
||||
type = 'list-box',
|
||||
})
|
||||
flow3.style.margin = 2
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'flow_buttons',
|
||||
type = 'flow',
|
||||
direction = 'horizontal',
|
||||
})
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'endorse_proposal',
|
||||
type = 'button',
|
||||
caption = 'Endorse Proposal',
|
||||
})
|
||||
flow4.style.minimal_width = 150
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow4.style.bottom_margin = 9
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'retract_endorsement',
|
||||
type = 'button',
|
||||
caption = 'Retract Endorsement',
|
||||
})
|
||||
flow4.style.minimal_width = 150
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow4.style.bottom_margin = 9
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'abandon_proposal',
|
||||
type = 'button',
|
||||
caption = 'Abandon Proposal',
|
||||
})
|
||||
flow4.style.minimal_width = 150
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
flow4.style.bottom_margin = 9
|
||||
|
||||
|
||||
-- PROPOSAL MAKER --
|
||||
|
||||
flow3 = GuiCommon.flow_add_subpanel(flow2, 'proposal_maker')
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'body',
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
flow4.style.horizontal_align = 'center'
|
||||
flow4.style.vertical_align = 'center'
|
||||
|
||||
flow5 = flow4.add({
|
||||
type = 'label',
|
||||
caption = 'Run name',
|
||||
})
|
||||
flow5.style.font = 'heading-3'
|
||||
|
||||
flow5 = flow4.add({
|
||||
name = 'namefield',
|
||||
type = 'textfield',
|
||||
caption = 'Name',
|
||||
text = '',
|
||||
})
|
||||
flow5.style.width = 150
|
||||
flow5.style.height = 24
|
||||
flow5.style.top_margin = -3
|
||||
flow5.style.bottom_margin = 3
|
||||
|
||||
flow5 = flow4.add({
|
||||
name = 'options',
|
||||
type = 'table',
|
||||
column_count = 2,
|
||||
})
|
||||
flow5.style.width = 200
|
||||
flow5.style.margin = 0
|
||||
|
||||
flow_add_proposal_slider(flow5, 'capacity', 'Capacity', #CoreData.capacity_options, 5, {'pirates.capacity_tooltip'})
|
||||
-- flow_add_proposal_slider(flow5, 'difficulty', 'Difficulty', #CoreData.difficulty_options, 2, {'pirates.difficulty_tooltip'})
|
||||
-- flow_add_proposal_switch(flow5, 'mode', 'Mode', 'left', {'pirates.mode_tooltip'})
|
||||
|
||||
-- flow5 = flow4.add({
|
||||
-- name = 'proposal_cant_do_infinity_mode',
|
||||
-- type = 'label',
|
||||
-- caption = 'Infinity mode isn\'t available at the moment.',
|
||||
-- })
|
||||
-- flow5.style.single_line = false
|
||||
-- flow5.style.maximal_width = 200
|
||||
|
||||
flow5 = flow4.add({
|
||||
name = 'proposal_disabled_low_crew_caps',
|
||||
type = 'label',
|
||||
caption = 'This capacity setting isn\'t available at the moment.',
|
||||
})
|
||||
flow5.style.single_line = false
|
||||
flow5.style.maximal_width = 200
|
||||
|
||||
flow5 = flow4.add({
|
||||
name = 'propose_crew',
|
||||
type = 'button',
|
||||
caption = 'Propose',
|
||||
})
|
||||
flow5.style.minimal_width = 75
|
||||
flow5.style.font = 'default-bold'
|
||||
flow5.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
|
||||
-- LAUNCH YOUR PROPOSAL --
|
||||
|
||||
flow3 = flow2.add({
|
||||
name = 'flow_proposal_launch',
|
||||
type = 'flow',
|
||||
direction = 'vertical',
|
||||
})
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'proposal_insufficient_endorsers',
|
||||
type = 'label',
|
||||
caption = 'Gather support from more pirates.',
|
||||
})
|
||||
flow4.style.single_line = false
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'proposal_crew_count_capped',
|
||||
type = 'label',
|
||||
caption = 'The number of concurrent runs on the server has reached the cap set by the admins.',
|
||||
})
|
||||
flow4.style.single_line = false
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'proposal_insufficient_player_capacity',
|
||||
type = 'label',
|
||||
caption = "Can't launch; at least one run needs high player capacity.",
|
||||
})
|
||||
flow4.style.single_line = false
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'proposal_insufficient_sloops',
|
||||
type = 'label',
|
||||
caption = 'No sloops available. Join an existing run instead.',
|
||||
})
|
||||
flow4.style.single_line = false
|
||||
|
||||
flow4 = flow3.add({
|
||||
name = 'launch_crew',
|
||||
type = 'button',
|
||||
caption = 'Launch run',
|
||||
})
|
||||
flow4.style.minimal_width = 150
|
||||
flow4.style.font = 'default-bold'
|
||||
flow4.style.font_color = {r=0.10, g=0.10, b=0.10}
|
||||
|
||||
|
||||
GuiCommon.flow_add_close_button(flow, window_name .. '_piratebutton')
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- function Public.regular_update(player)
|
||||
|
||||
-- end
|
||||
|
||||
|
||||
function Public.full_update(player)
|
||||
if Public.regular_update then Public.regular_update(player) end
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if not player.gui.screen['runs_piratewindow'] then return end
|
||||
local flow = player.gui.screen['runs_piratewindow']
|
||||
local playercrew_status = GuiCommon.crew_overall_state_bools(player.index)
|
||||
if not playercrew_status then return end
|
||||
|
||||
|
||||
--*** WHAT TO SHOW ***--
|
||||
|
||||
flow.ongoing_runs.visible = (#global_memory.crew_active_ids > 0)
|
||||
if flow.ongoing_runs.visible then
|
||||
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)
|
||||
|
||||
local selected_joinable_bool = false
|
||||
local crewid
|
||||
if bool1 then
|
||||
crewid = tonumber((flow.ongoing_runs.body.ongoing_runs_listbox.get_item(flow.ongoing_runs.body.ongoing_runs_listbox.selected_index))[2])
|
||||
selected_joinable_bool = bool1 and crewid and (global_memory.crew_memories[crewid].crewstatus == Crew.enum.ADVENTURING)
|
||||
end
|
||||
|
||||
flow.ongoing_runs.body.helpful_tip.visible = not (playercrew_status.leaving or playercrew_status.adventuring or playercrew_status.spectating)
|
||||
|
||||
flow.ongoing_runs.body.flow_buttons.visible = selected_joinable_bool or playercrew_status.spectating
|
||||
flow.ongoing_runs.body.flow_buttons.join_spectators.visible = selected_joinable_bool
|
||||
flow.ongoing_runs.body.flow_buttons.leave_spectators.visible = playercrew_status.spectating
|
||||
flow.ongoing_runs.body.flow_buttons.join_crew.visible = selected_joinable_bool and (not (crewid and global_memory.crew_memories[crewid] and (global_memory.crew_memories[crewid].crewstatus == Crew.enum.LEAVING_INITIAL_DOCK or #global_memory.crew_memories[crewid].crewplayerindices >= global_memory.crew_memories[crewid].capacity or (global_memory.crew_memories[crewid].tempbanned_from_joining_data and global_memory.crew_memories[crewid].tempbanned_from_joining_data[player.index] and game.tick < global_memory.crew_memories[crewid].tempbanned_from_joining_data[player.index] + Common.ban_from_rejoining_crew_ticks))))
|
||||
|
||||
flow.ongoing_runs.body.wait_to_join.visible = selected_joinable_bool and crewid and global_memory.crew_memories[crewid] and (global_memory.crew_memories[crewid].tempbanned_from_joining_data and global_memory.crew_memories[crewid].tempbanned_from_joining_data[player.index] and game.tick < global_memory.crew_memories[crewid].tempbanned_from_joining_data[player.index] + Common.ban_from_rejoining_crew_ticks) and (not (global_memory.crew_memories[crewid].crewstatus == Crew.enum.LEAVING_INITIAL_DOCK or #global_memory.crew_memories[crewid].crewplayerindices >= global_memory.crew_memories[crewid].capacity))
|
||||
if flow.ongoing_runs.body.wait_to_join.visible then
|
||||
flow.ongoing_runs.body.wait_to_join.caption = 'Wait to join... ' .. Math.ceil(((global_memory.crew_memories[crewid].tempbanned_from_joining_data[player.index] - (game.tick - Common.ban_from_rejoining_crew_ticks)))/60)
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
flow.proposals.visible = (memory.crewstatus == nil and not playercrew_status.leaving)
|
||||
if flow.proposals.visible then
|
||||
if playercrew_status.proposing then
|
||||
flow.proposals.body.proposals_listbox.selected_index = 0
|
||||
flow.proposals.body.proposals_listbox.selected_index = 0
|
||||
end
|
||||
|
||||
flow.proposals.body.proposals_listbox.visible = (not playercrew_status.leaving) and (#global_memory.crewproposals > 0)
|
||||
|
||||
flow.proposals.body.flow_buttons.endorse_proposal.visible = (not playercrew_status.leaving) and (not playercrew_status.endorsing) and (#global_memory.crewproposals > 0) and flow.proposals.body.proposals_listbox.selected_index ~= 0
|
||||
|
||||
flow.proposals.body.flow_buttons.abandon_proposal.visible = (not playercrew_status.leaving) and playercrew_status.endorsing and playercrew_status.endorsing and playercrew_status.proposing and (#global_memory.crewproposals > 0)
|
||||
|
||||
flow.proposals.body.flow_buttons.retract_endorsement.visible = (not playercrew_status.leaving) and playercrew_status.endorsing and (not playercrew_status.proposing) and (#global_memory.crewproposals > 0)
|
||||
|
||||
flow.proposals.body.proposal_maker.visible = (not playercrew_status.leaving) and (not playercrew_status.endorsing)
|
||||
|
||||
flow.proposals.body.flow_proposal_launch.proposal_insufficient_sloops.visible = playercrew_status.sloops_full
|
||||
|
||||
flow.proposals.body.flow_proposal_launch.proposal_insufficient_player_capacity.visible = playercrew_status.needs_more_capacity
|
||||
|
||||
flow.proposals.body.flow_proposal_launch.proposal_crew_count_capped.visible = playercrew_status.crew_count_capped
|
||||
|
||||
flow.proposals.body.flow_proposal_launch.proposal_insufficient_endorsers.visible = playercrew_status.needs_more_endorsers
|
||||
|
||||
-- flow.proposals.body.proposal_maker.body.proposal_cant_do_infinity_mode.visible = (flow.proposals.body.proposal_maker.body.options.mode.mode.switch.switch_state == 'right')
|
||||
|
||||
-- flow.proposals.body.proposal_maker.body.proposal_disabled_low_crew_caps.visible = false
|
||||
flow.proposals.body.proposal_maker.body.proposal_disabled_low_crew_caps.visible = (flow.proposals.body.proposal_maker.body.options.capacity.capacity.slider.slider_value < global_memory.minimum_capacity_slider_value)
|
||||
|
||||
flow.proposals.body.proposal_maker.body.propose_crew.visible = (flow.proposals.body.proposal_maker.body.proposal_disabled_low_crew_caps.visible == false)
|
||||
-- flow.proposals.body.proposal_maker.body.propose_crew.visible = (flow.proposals.body.proposal_maker.body.proposal_cant_do_infinity_mode.visible == false) and (flow.proposals.body.proposal_maker.body.proposal_disabled_low_crew_caps.visible == false)
|
||||
|
||||
flow.proposals.body.flow_proposal_launch.launch_crew.visible = playercrew_status.proposal_can_launch
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--*** UPDATE CONTENT ***--
|
||||
|
||||
if flow.ongoing_runs.visible then
|
||||
local wrappedmemories = {}
|
||||
for _, mem in pairs(global_memory.crew_memories) do
|
||||
local count = 0
|
||||
if mem.crewstatus and mem.crewstatus == Crew.enum.LEAVING_INITIAL_DOCK then
|
||||
count = Boats.players_on_boat_count(mem.boat)
|
||||
elseif mem.crewplayerindices then
|
||||
count = #mem.crewplayerindices
|
||||
end
|
||||
wrappedmemories[#wrappedmemories + 1] = {'pirates.run_displayform', mem.id, mem.name .. ', ' .. CoreData.difficulty_options[mem.difficulty_option].text .. ', [item=light-armor]' .. count .. CoreData.capacity_options[mem.capacity_option].text2 .. ', [item=rail] ' .. (mem.overworldx or 0)}
|
||||
-- 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)
|
||||
end
|
||||
|
||||
if flow.proposals.visible then
|
||||
local wrappedproposals = {}
|
||||
for _, proposal in pairs(global_memory.crewproposals) do
|
||||
wrappedproposals[#wrappedproposals + 1] = {'pirates.proposal_displayform', proposal.name, Utils.spritepath_to_richtext(CoreData.capacity_options[proposal.capacity_option].icon)}
|
||||
-- wrappedproposals[#wrappedproposals + 1] = {'pirates.proposal_displayform', proposal.name, Utils.spritepath_to_richtext(CoreData.difficulty_options[proposal.difficulty_option].icon), Utils.spritepath_to_richtext(CoreData.capacity_options[proposal.capacity_option].icon)}
|
||||
end
|
||||
GuiCommon.update_listbox(flow.proposals.body.proposals_listbox, wrappedproposals)
|
||||
end
|
||||
|
||||
-- update proposal maker
|
||||
if flow.proposals.body.proposal_maker.visible then
|
||||
local capacity_slider_value = flow.proposals.body.proposal_maker.body.options.capacity.capacity.slider.slider_value
|
||||
for i, opt in pairs(CoreData.capacity_options) do
|
||||
if capacity_slider_value == i then
|
||||
flow.proposals.body.proposal_maker.body.options.capacity.capacity.readoff_text.caption = opt.text
|
||||
flow.proposals.body.proposal_maker.body.options.capacity_readoff_icon.sprite = opt.icon
|
||||
end
|
||||
end
|
||||
if flow.proposals.body.proposal_maker.body.options.capacity.capacity.readoff_text.caption == '∞' then flow.proposals.body.proposal_maker.body.options.capacity.capacity.readoff_text.caption = 'No limit' end
|
||||
|
||||
-- local difficulty_slider_value = flow.proposals.body.proposal_maker.body.options.difficulty.difficulty.slider.slider_value
|
||||
-- for i, opt in pairs(CoreData.difficulty_options) do
|
||||
-- if difficulty_slider_value == i then
|
||||
-- flow.proposals.body.proposal_maker.body.options.difficulty.difficulty.readoff_text.caption = opt.text
|
||||
-- flow.proposals.body.proposal_maker.body.options.difficulty_readoff_icon.sprite = opt.icon
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- local mode_switch_state = flow.proposals.body.proposal_maker.body.options.mode.mode.switch.switch_state
|
||||
-- for i, opt in pairs(CoreData.mode_options) do
|
||||
-- if mode_switch_state == i then
|
||||
-- flow.proposals.body.proposal_maker.body.options.mode.mode.readoff_text.caption = opt.text
|
||||
-- flow.proposals.body.proposal_maker.body.options.mode_readoff_icon.sprite = opt.icon
|
||||
-- end
|
||||
-- end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function Public.click(event)
|
||||
|
||||
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 global_memory = Memory.get_global_memory()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
|
||||
if eventname == 'join_spectators' then
|
||||
local listbox = flow.ongoing_runs.body.ongoing_runs_listbox
|
||||
|
||||
Crew.join_spectators(player, tonumber(listbox.get_item(listbox.selected_index)[2]))
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'leave_spectators' then
|
||||
Crew.leave_spectators(player)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'join_crew' then
|
||||
local listbox = flow.ongoing_runs.body.ongoing_runs_listbox
|
||||
|
||||
Crew.join_crew(player, tonumber(listbox.get_item(listbox.selected_index)[2]))
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'propose_crew' then
|
||||
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)
|
||||
|
||||
local capacity_option = flow.proposals.body.proposal_maker.body.options.capacity.capacity.slider.slider_value
|
||||
local difficulty_option = 1
|
||||
-- local difficulty_option = flow.proposals.body.proposal_maker.body.options.difficulty.difficulty.slider.slider_value
|
||||
-- local mode_option = flow.proposals.body.proposal_maker.body.options.mode.mode.switch.switch_state
|
||||
|
||||
if (not proposal_name) or (proposal_name == '') then proposal_name = 'NoName' end
|
||||
|
||||
-- make name unique
|
||||
-- local unique, changed = true, false
|
||||
-- local check_unique = function(name)
|
||||
-- unique = true
|
||||
-- for _, proposal in pairs(global_memory.crewproposals) do
|
||||
-- if name == proposal.name then
|
||||
-- unique = false
|
||||
-- changed = true
|
||||
-- break
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- local i = 0
|
||||
-- check_unique()
|
||||
-- while i < 10 and not unique do
|
||||
-- check_unique(proposal_name .. i)
|
||||
-- i = i + 1
|
||||
-- end
|
||||
-- if not unique then return end
|
||||
-- if changed then proposal_name = proposal_name .. i end
|
||||
|
||||
local unique = true
|
||||
for _, proposal in pairs(global_memory.crewproposals) do
|
||||
if proposal_name == proposal.name then
|
||||
unique = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not unique then return end
|
||||
|
||||
local proposal = {
|
||||
name = proposal_name,
|
||||
difficulty_option = difficulty_option,
|
||||
capacity_option = capacity_option,
|
||||
-- mode_option = mode_option,
|
||||
endorserindices = {player.index},
|
||||
}
|
||||
|
||||
global_memory.crewproposals[#global_memory.crewproposals + 1] = proposal
|
||||
|
||||
local message = player.name .. ' proposed the run ' .. proposal_name .. ' [capacity ' .. CoreData.capacity_options[capacity_option].text3 .. '].'
|
||||
-- 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
|
||||
|
||||
if eventname == 'endorse_proposal' then
|
||||
local lb = flow.proposals.body.proposals_listbox
|
||||
|
||||
local index = lb.selected_index
|
||||
if index ~= 0 then
|
||||
local name2 = lb.get_item(lb.selected_index)[2]
|
||||
|
||||
for _, proposal in pairs(global_memory.crewproposals) do
|
||||
|
||||
if proposal.name == name2 and #proposal.endorserindices < CoreData.capacity_options[proposal.capacity_option].value then
|
||||
proposal.endorserindices[#proposal.endorserindices + 1] = player.index
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'abandon_proposal' then
|
||||
Crew.player_abandon_proposal(player)
|
||||
Crew.player_abandon_endorsements(player)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'retract_endorsement' then
|
||||
Crew.player_abandon_endorsements(player)
|
||||
return
|
||||
end
|
||||
|
||||
if eventname == 'launch_crew' then
|
||||
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
|
||||
Crew.initialise_crew(proposal)
|
||||
global_memory.crewproposals[k] = nil
|
||||
Progression.set_off_from_starting_dock()
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return Public
|
619
maps/pirates/highscore.lua
Normal file
619
maps/pirates/highscore.lua
Normal file
@ -0,0 +1,619 @@
|
||||
-- Adapted from mountain_fortress_v3 highscores.lua
|
||||
|
||||
local Event = require 'utils.event'
|
||||
local Global = require 'utils.global'
|
||||
local Server = require 'utils.server'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local Token = require 'utils.token'
|
||||
local Tabs = require 'utils.gui'
|
||||
require 'utils.core'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local SpamProtection = require 'utils.spam_protection'
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
|
||||
local module_name = 'Highscore'
|
||||
local score_dataset = 'highscores'
|
||||
local score_key = 'pirate_ship_scores'
|
||||
local score_key_debug = 'pirate_ship_scores_debug'
|
||||
local score_key_modded = 'pirate_ship_scores_modded'
|
||||
|
||||
local Public = {}
|
||||
local insert = table.insert
|
||||
local this = {
|
||||
score_table = {player = {}},
|
||||
sort_by = {}
|
||||
}
|
||||
|
||||
Global.register(
|
||||
this,
|
||||
function(t)
|
||||
this = t
|
||||
end
|
||||
)
|
||||
|
||||
local function sort_list(method, column_name, score_list)
|
||||
local comparators = {
|
||||
['ascending'] = function(a, b)
|
||||
if column_name == 'completion_time' then
|
||||
return (a[column_name] < b[column_name]) and not (a[column_name] == 0 and b[column_name] ~= 0)
|
||||
else
|
||||
return a[column_name] < b[column_name]
|
||||
end
|
||||
end,
|
||||
['descending'] = function(a, b)
|
||||
if column_name == 'completion_time' then
|
||||
return (a[column_name] > b[column_name])
|
||||
else
|
||||
return a[column_name] > b[column_name]
|
||||
end
|
||||
end
|
||||
}
|
||||
Utils.stable_sort(score_list, comparators[method])
|
||||
-- table.sort(score_list, comparators[method])
|
||||
return score_list
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function get_tables_of_scores_by_type(scores)
|
||||
|
||||
local completion_times = {}
|
||||
local leagues_travelled = {}
|
||||
local completion_times_mediump_latestv = {}
|
||||
local leagues_travelled_mediump_latestv = {}
|
||||
local completion_times_hard = {}
|
||||
local leagues_travelled_hard = {}
|
||||
local completion_times_nightmare = {}
|
||||
local leagues_travelled_nightmare = {}
|
||||
local completion_times_latestv = {}
|
||||
local leagues_travelled_latestv = {}
|
||||
local versions = {}
|
||||
|
||||
for _, score in pairs(scores) do
|
||||
if score.version and score.version > 0 then
|
||||
versions[#versions + 1] = score.version
|
||||
end
|
||||
if score.completion_time and score.completion_time > 0 then
|
||||
completion_times[#completion_times + 1] = score.completion_time
|
||||
end
|
||||
if score.leagues_travelled and score.leagues_travelled > 0 then
|
||||
leagues_travelled[#leagues_travelled + 1] = score.leagues_travelled
|
||||
end
|
||||
if score.difficulty and score.difficulty >= 1.5 then
|
||||
if score.completion_time and score.completion_time > 0 then
|
||||
completion_times_hard[#completion_times_hard + 1] = score.completion_time
|
||||
end
|
||||
if score.leagues_travelled and score.leagues_travelled > 0 then
|
||||
leagues_travelled_hard[#leagues_travelled_hard + 1] = score.leagues_travelled
|
||||
end
|
||||
end
|
||||
if score.difficulty and score.difficulty >= 3 then
|
||||
if score.completion_time and score.completion_time > 0 then
|
||||
completion_times_nightmare[#completion_times_nightmare + 1] = score.completion_time
|
||||
end
|
||||
if score.leagues_travelled and score.leagues_travelled > 0 then
|
||||
leagues_travelled_nightmare[#leagues_travelled_nightmare + 1] = score.leagues_travelled
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local latest_version = 0
|
||||
for _, v in pairs(versions) do
|
||||
if v > latest_version then latest_version = v end
|
||||
end
|
||||
|
||||
for _, score in pairs(scores) do
|
||||
if score.version and score.version == latest_version then
|
||||
if score.completion_time and score.completion_time > 0 then
|
||||
completion_times_latestv[#completion_times_latestv + 1] = score.completion_time
|
||||
end
|
||||
if score.leagues_travelled and score.leagues_travelled > 0 then
|
||||
leagues_travelled_latestv[#leagues_travelled_latestv + 1] = score.leagues_travelled
|
||||
end
|
||||
if score.difficulty and score.difficulty >= 1 then
|
||||
if score.completion_time and score.completion_time > 0 then
|
||||
completion_times_mediump_latestv[#completion_times_mediump_latestv + 1] = score.completion_time
|
||||
end
|
||||
if score.leagues_travelled and score.leagues_travelled > 0 then
|
||||
leagues_travelled_mediump_latestv[#leagues_travelled_mediump_latestv + 1] = score.leagues_travelled
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(completion_times)
|
||||
table.sort(leagues_travelled)
|
||||
table.sort(completion_times_mediump_latestv)
|
||||
table.sort(leagues_travelled_mediump_latestv)
|
||||
table.sort(completion_times_hard)
|
||||
table.sort(leagues_travelled_hard)
|
||||
table.sort(completion_times_nightmare)
|
||||
table.sort(leagues_travelled_nightmare)
|
||||
table.sort(completion_times_latestv)
|
||||
table.sort(leagues_travelled_latestv)
|
||||
|
||||
return {
|
||||
latest_version = latest_version,
|
||||
completion_times = completion_times,
|
||||
leagues_travelled = leagues_travelled,
|
||||
completion_times_mediump_latestv = completion_times_mediump_latestv,
|
||||
leagues_travelled_mediump_latestv = leagues_travelled_mediump_latestv,
|
||||
completion_times_hard = completion_times_hard,
|
||||
leagues_travelled_hard = leagues_travelled_hard,
|
||||
completion_times_nightmare = completion_times_nightmare,
|
||||
leagues_travelled_nightmare = leagues_travelled_nightmare,
|
||||
completion_times_latestv = completion_times_latestv,
|
||||
leagues_travelled_latestv = leagues_travelled_latestv,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
local function get_score_cuttofs(tables_of_scores_by_type)
|
||||
|
||||
local completion_times_cutoff = #tables_of_scores_by_type.completion_times > 8 and tables_of_scores_by_type.completion_times[8] or 9999999
|
||||
local completion_times_mediump_latestv_cutoff = #tables_of_scores_by_type.completion_times_mediump_latestv > 4 and tables_of_scores_by_type.completion_times_mediump_latestv[4] or 9999999
|
||||
local completion_times_hard_cutoff = #tables_of_scores_by_type.completion_times_hard > 4 and tables_of_scores_by_type.completion_times_hard[4] or 9999999
|
||||
local completion_times_nightmare_cutoff = #tables_of_scores_by_type.completion_times_hard > 2 and tables_of_scores_by_type.completion_times_hard[2] or 9999999
|
||||
local completion_times_latestv_cutoff = #tables_of_scores_by_type.completion_times_latestv > 8 and tables_of_scores_by_type.completion_times_latestv[8] or 9999999
|
||||
|
||||
local leagues_travelled_cutoff = #tables_of_scores_by_type.leagues_travelled > 8 and tables_of_scores_by_type.leagues_travelled[-8] or 0
|
||||
local leagues_travelled_mediump_latestv_cutoff = #tables_of_scores_by_type.leagues_travelled_mediump_latestv > 4 and tables_of_scores_by_type.leagues_travelled_mediump_latestv[-4] or 0
|
||||
local leagues_travelled_hard_cutoff = #tables_of_scores_by_type.leagues_travelled_hard > 4 and tables_of_scores_by_type.leagues_travelled_hard[-4] or 0
|
||||
local leagues_travelled_nightmare_cutoff = #tables_of_scores_by_type.leagues_travelled_hard > 2 and tables_of_scores_by_type.leagues_travelled_hard[-2] or 0
|
||||
local leagues_travelled_latestv_cutoff = #tables_of_scores_by_type.leagues_travelled_latestv > 86 and tables_of_scores_by_type.leagues_travelled_latestv[-8] or 0
|
||||
|
||||
return {
|
||||
completion_times_cutoff = completion_times_cutoff,
|
||||
completion_times_mediump_latestv_cutoff = completion_times_mediump_latestv_cutoff,
|
||||
completion_times_hard_cutoff = completion_times_hard_cutoff,
|
||||
completion_times_nightmare_cutoff = completion_times_nightmare_cutoff,
|
||||
completion_times_latestv_cutoff = completion_times_latestv_cutoff,
|
||||
leagues_travelled_cutoff = leagues_travelled_cutoff,
|
||||
leagues_travelled_mediump_latestv_cutoff = leagues_travelled_mediump_latestv_cutoff,
|
||||
leagues_travelled_hard_cutoff = leagues_travelled_hard_cutoff,
|
||||
leagues_travelled_nightmare_cutoff = leagues_travelled_nightmare_cutoff,
|
||||
leagues_travelled_latestv_cutoff = leagues_travelled_latestv_cutoff,
|
||||
}
|
||||
end
|
||||
|
||||
local function saved_scores_trim(scores)
|
||||
-- the goal here is to trim away highscores so we don't have too many.
|
||||
|
||||
local tables_of_scores_by_type = get_tables_of_scores_by_type(scores)
|
||||
|
||||
local cutoffs = get_score_cuttofs(tables_of_scores_by_type)
|
||||
|
||||
-- log(_inspect{completion_times_cutoff,completion_times_mediump_latestv_cutoff,completion_times_hard_cutoff,completion_times_latestv_cutoff,leagues_travelled_cutoff,leagues_travelled_mediump_latestv_cutoff,leagues_travelled_hard_cutoff,leagues_travelled_latestv_cutoff})
|
||||
|
||||
local delete = {}
|
||||
|
||||
for secs_id, score in pairs(scores) do
|
||||
local include = false
|
||||
|
||||
if cutoffs.completion_times_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_cutoff then include = true
|
||||
elseif cutoffs.completion_times_mediump_latestv_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_mediump_latestv_cutoff and score.version == cutoffs.latest_version and score.difficulty >= 1 then include = true
|
||||
elseif cutoffs.completion_times_hard_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_hard_cutoff and score.difficulty >= 1.5 then include = true
|
||||
elseif cutoffs.completion_times_nightmare_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_nightmare_cutoff and score.difficulty >=3 then include = true
|
||||
elseif cutoffs.completion_times_latestv_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_latestv_cutoff and score.version == cutoffs.latest_version then include = true
|
||||
|
||||
elseif cutoffs.leagues_travelled_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_cutoff then include = true
|
||||
elseif cutoffs.leagues_travelled_mediump_latestv_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_mediump_latestv_cutoff and score.version == cutoffs.latest_version and score.difficulty >= 1 then include = true
|
||||
elseif cutoffs.leagues_travelled_hard_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_hard_cutoff and score.difficulty >= 1.5 then include = true
|
||||
elseif cutoffs.leagues_travelled_nightmare_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_nightmare_cutoff and score.difficulty >= 3 then include = true
|
||||
elseif cutoffs.leagues_travelled_latestv_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_latestv_cutoff and score.version == cutoffs.latest_version then include = true
|
||||
end
|
||||
|
||||
if not include then delete[#delete + 1] = secs_id end
|
||||
end
|
||||
-- log(_inspect(delete))
|
||||
|
||||
for _, secs_id in pairs(delete) do
|
||||
scores[secs_id] = nil
|
||||
end
|
||||
|
||||
return scores
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
local function local_highscores_write_stats(crew_secs_id, name, captain_name, completion_time, leagues_travelled, version, difficulty, max_players)
|
||||
|
||||
if not this.score_table['player'] then this.score_table['player'] = {} end
|
||||
if not this.score_table['player'].runs then this.score_table['player'].runs = {} end
|
||||
|
||||
local t = this.score_table['player']
|
||||
|
||||
if t then
|
||||
-- if name then
|
||||
-- t.name = name
|
||||
-- end
|
||||
-- if version then
|
||||
-- t.version = version
|
||||
-- end
|
||||
-- if completion_time then
|
||||
-- t.completion_time = completion_time
|
||||
-- end
|
||||
-- if leagues_travelled then
|
||||
-- t.leagues_travelled = leagues_travelled
|
||||
-- end
|
||||
-- if difficulty then
|
||||
-- t.difficulty = difficulty
|
||||
-- end
|
||||
-- if max_players then
|
||||
-- t.max_players = max_players
|
||||
-- end
|
||||
|
||||
if crew_secs_id then
|
||||
t.runs[crew_secs_id] = {name = name, captain_name = captain_name, version = version, completion_time = completion_time, leagues_travelled = leagues_travelled, difficulty = difficulty, max_players = max_players}
|
||||
|
||||
-- log(_inspect(t))
|
||||
|
||||
saved_scores_trim(t.runs)
|
||||
end
|
||||
end
|
||||
|
||||
this.score_table['player'] = t
|
||||
-- log(_inspect(t))
|
||||
end
|
||||
|
||||
|
||||
local load_in_scores =
|
||||
Token.register(
|
||||
function(data)
|
||||
local value = data.value
|
||||
if not this.score_table['player'] then
|
||||
this.score_table['player'] = {}
|
||||
end
|
||||
|
||||
this.score_table['player'] = value
|
||||
end
|
||||
)
|
||||
function Public.load_in_scores()
|
||||
local secs = Server.get_current_time()
|
||||
-- if secs then game.print('secs2: ' .. secs) else game.print('secs: false') end
|
||||
if not secs then
|
||||
return
|
||||
else
|
||||
-- FULL CLEAN task (erases everything...):
|
||||
-- server_set_data(score_dataset, score_key, {})
|
||||
|
||||
if is_game_modded() then
|
||||
Server.try_get_data(score_dataset, score_key_modded, load_in_scores)
|
||||
elseif _DEBUG then
|
||||
Server.try_get_data(score_dataset, score_key_debug, load_in_scores)
|
||||
else
|
||||
Server.try_get_data(score_dataset, score_key, load_in_scores)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.dump_highscores()
|
||||
log(_inspect(this.score_table['player']))
|
||||
end
|
||||
|
||||
function Public.overwrite_scores_specific()
|
||||
-- the correct format is to put _everything_ from a dump into the third argument:
|
||||
-- Server.set_data(score_dataset, score_key, )
|
||||
-- return true
|
||||
return nil
|
||||
end
|
||||
|
||||
function Public.write_score(crew_secs_id, name, captain_name, completion_time, leagues_travelled, version, difficulty, max_players)
|
||||
local secs = Server.get_current_time()
|
||||
-- if secs then game.print('secs1: ' .. secs) else game.print('secs: false') end
|
||||
if not secs then
|
||||
return
|
||||
else
|
||||
local_highscores_write_stats(crew_secs_id, name, captain_name, completion_time, leagues_travelled, version, difficulty, max_players)
|
||||
|
||||
if is_game_modded() then
|
||||
Server.set_data(score_dataset, score_key_modded, this.score_table['player'])
|
||||
elseif _DEBUG then
|
||||
Server.set_data(score_dataset, score_key_debug, this.score_table['player'])
|
||||
else
|
||||
Server.set_data(score_dataset, score_key, this.score_table['player'])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_init()
|
||||
local secs = Server.get_current_time()
|
||||
if not secs then
|
||||
local_highscores_write_stats() --just to init tables presumably
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local sorting_symbol = {ascending = '▲', descending = '▼'}
|
||||
|
||||
local function get_saved_scores_for_displaying()
|
||||
local score_data = this.score_table['player']
|
||||
local score_list = {}
|
||||
|
||||
if score_data and score_data.runs then
|
||||
for _, score in pairs(score_data.runs or {}) do
|
||||
insert(
|
||||
score_list,
|
||||
{
|
||||
name = score and score.name,
|
||||
captain_name = score and score.captain_name,
|
||||
completion_time = score and score.completion_time or 99999,
|
||||
leagues_travelled = score and score.leagues_travelled or 0,
|
||||
version = score and score.version or 0,
|
||||
difficulty = score and score.difficulty or 0,
|
||||
max_players = score and score.max_players or 0,
|
||||
}
|
||||
)
|
||||
end
|
||||
else
|
||||
score_list[#score_list + 1] = {
|
||||
name = 'Nothing here yet',
|
||||
captain_name = '',
|
||||
completion_time = 0,
|
||||
leagues_travelled = 0,
|
||||
version = 0,
|
||||
difficulty = 0,
|
||||
max_players = 0,
|
||||
}
|
||||
end
|
||||
|
||||
return score_list
|
||||
end
|
||||
|
||||
local function score_gui(data)
|
||||
local player = data.player
|
||||
local frame = data.frame
|
||||
frame.clear()
|
||||
|
||||
local columnwidth = 96
|
||||
|
||||
-- local flow = frame.add {type = 'flow'}
|
||||
-- local sFlow = flow.style
|
||||
-- sFlow.horizontally_stretchable = true
|
||||
-- sFlow.horizontal_align = 'center'
|
||||
-- sFlow.vertical_align = 'center'
|
||||
|
||||
-- local stats = flow.add {type = 'label', caption = 'Highest score so far:'}
|
||||
-- local s_stats = stats.style
|
||||
-- s_stats.font = 'heading-1'
|
||||
-- s_stats.font_color = {r = 0.98, g = 0.66, b = 0.22}
|
||||
-- s_stats.horizontal_align = 'center'
|
||||
-- s_stats.vertical_align = 'center'
|
||||
|
||||
-- -- Global stats : rockets, biters kills
|
||||
-- add_global_stats(frame)
|
||||
|
||||
-- -- Separator
|
||||
-- local line = frame.add {type = 'line'}
|
||||
-- line.style.top_margin = 8
|
||||
-- line.style.bottom_margin = 8
|
||||
|
||||
-- Score per player
|
||||
local t = frame.add {type = 'table', column_count = 7}
|
||||
|
||||
-- Score headers
|
||||
local headers = {
|
||||
{name = '_name', caption = 'Crew'},
|
||||
{name = '_captain_name', caption = 'Captain'},
|
||||
{column = 'completion_time', name = '_completion_time', caption = 'Completion'},
|
||||
{column = 'leagues_travelled', name = '_leagues_travelled', caption = 'Leagues'},
|
||||
{column = 'version', name = '_version', caption = 'Version'},
|
||||
{column = 'difficulty', name = '_difficulty', caption = 'Difficulty'},
|
||||
{column = 'max_players', name = '_max_players', caption = 'PeakPlayers'},
|
||||
}
|
||||
|
||||
local sorting_pref = this.sort_by[player.index] or {}
|
||||
for _, header in ipairs(headers) do
|
||||
local cap = header.caption
|
||||
|
||||
-- log(header.caption)
|
||||
|
||||
-- Add sorting symbol if any
|
||||
if header.column and sorting_pref[1] and sorting_pref[1].column == header.column then
|
||||
local symbol = sorting_symbol[sorting_pref[1].method]
|
||||
cap = symbol .. cap
|
||||
end
|
||||
|
||||
-- Header
|
||||
local label =
|
||||
t.add {
|
||||
type = 'label',
|
||||
caption = cap,
|
||||
name = header.name
|
||||
}
|
||||
label.style.font = 'default-listbox'
|
||||
label.style.font_color = {r = 0.98, g = 0.66, b = 0.22} -- yellow
|
||||
label.style.minimal_width = columnwidth
|
||||
label.style.horizontal_align = 'right'
|
||||
end
|
||||
|
||||
-- Score list
|
||||
local score_list = get_saved_scores_for_displaying()
|
||||
-- log(_inspect(score_list))
|
||||
|
||||
for i = #sorting_pref, 1, -1 do
|
||||
local sort = sorting_pref[i]
|
||||
if sort then
|
||||
score_list = sort_list(sort.method, sort.column, score_list)
|
||||
end
|
||||
end
|
||||
|
||||
-- New pane for scores (while keeping headers at same position)
|
||||
local scroll_pane =
|
||||
frame.add(
|
||||
{
|
||||
type = 'scroll-pane',
|
||||
name = 'score_scroll_pane',
|
||||
direction = 'vertical',
|
||||
horizontal_scroll_policy = 'never',
|
||||
vertical_scroll_policy = 'auto'
|
||||
}
|
||||
)
|
||||
scroll_pane.style.maximal_height = 400
|
||||
t = scroll_pane.add {type = 'table', column_count = 7}
|
||||
|
||||
-- Score entries
|
||||
for _, entry in pairs(score_list) do
|
||||
local p = {color = {r = Math.random(1, 255), g = Math.random(1, 255), b = Math.random(1, 255)}}
|
||||
-- local p
|
||||
-- if not (entry and entry.name) then
|
||||
-- p = {color = {r = random(1, 255), g = random(1, 255), b = random(1, 255)}}
|
||||
-- else
|
||||
-- p = game.players[entry.name]
|
||||
-- if not p then
|
||||
-- p = {color = {r = random(1, 255), g = random(1, 255), b = random(1, 255)}}
|
||||
-- end
|
||||
-- end
|
||||
local special_color = {
|
||||
r = p.color.r * 0.6 + 0.4,
|
||||
g = p.color.g * 0.6 + 0.4,
|
||||
b = p.color.b * 0.6 + 0.4,
|
||||
a = 1,
|
||||
}
|
||||
|
||||
-- displayforms:
|
||||
local n = entry.completion_time > 0 and Utils.time_mediumform(entry.completion_time or 0) or 'N/A'
|
||||
local l = entry.leagues_travelled > 0 and entry.leagues_travelled or '?'
|
||||
local v = entry.version > 0 and entry.version or '?'
|
||||
local d = entry.difficulty > 0 and CoreData.get_difficulty_name_from_value(entry.difficulty) or '?'
|
||||
local c = entry.max_players > 0 and entry.max_players or '?'
|
||||
local line = {
|
||||
{caption = entry.name, color = special_color},
|
||||
{caption = entry.captain_name or '?'},
|
||||
{caption = tostring(n)},
|
||||
{caption = tostring(l)},
|
||||
{caption = tostring(v)},
|
||||
{caption = tostring(d)},
|
||||
{caption = tostring(c)},
|
||||
}
|
||||
local default_color = {r = 0.9, g = 0.9, b = 0.9}
|
||||
|
||||
for _, column in ipairs(line) do
|
||||
local label =
|
||||
t.add {
|
||||
type = 'label',
|
||||
caption = column.caption,
|
||||
color = column.color or default_color,
|
||||
}
|
||||
label.style.font = 'default'
|
||||
label.style.minimal_width = columnwidth
|
||||
label.style.maximal_width = columnwidth
|
||||
label.style.horizontal_align = 'right'
|
||||
end -- foreach column
|
||||
end -- foreach entry
|
||||
end
|
||||
|
||||
local score_gui_token = Token.register(score_gui)
|
||||
|
||||
local function on_gui_click(event)
|
||||
if not event then
|
||||
return
|
||||
end
|
||||
if not event.element then
|
||||
return
|
||||
end
|
||||
if not event.element.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local player = game.players[event.element.player_index]
|
||||
local frame = Tabs.comfy_panel_get_active_frame(player)
|
||||
if not frame then
|
||||
return
|
||||
end
|
||||
if frame.name ~= module_name then
|
||||
return
|
||||
end
|
||||
|
||||
local is_spamming = SpamProtection.is_spamming(player, nil, 'HighScore Gui Click')
|
||||
if is_spamming then
|
||||
return
|
||||
end
|
||||
|
||||
local name = event.element.name
|
||||
|
||||
-- Handles click on a score header
|
||||
local element_to_column = {
|
||||
['_version'] = 'version',
|
||||
['_completion_time'] = 'completion_time',
|
||||
['_leagues_travelled'] = 'leagues_travelled',
|
||||
['_difficulty'] = 'difficulty',
|
||||
['_max_players'] = 'max_players',
|
||||
}
|
||||
if element_to_column[name] then
|
||||
--@TODO: Extend
|
||||
local sorting_pref = this.sort_by[player.index]
|
||||
local found_index = nil
|
||||
local new_method = 'descending'
|
||||
|
||||
for i, sort in ipairs(sorting_pref) do
|
||||
if sort.column == element_to_column[name] then
|
||||
found_index = i
|
||||
if sort.method == 'descending' and i==1 then new_method = 'ascending' end
|
||||
end
|
||||
end
|
||||
if found_index then
|
||||
--remove this and shuffle everything before it up by 1:
|
||||
for j = found_index, 2, -1 do
|
||||
sorting_pref[j] = Utils.deepcopy(sorting_pref[j-1]) --deepcopy just as I'm slightly unsure about refernces here
|
||||
end
|
||||
else
|
||||
--prepend:
|
||||
for j = #sorting_pref + 1, 2, -1 do
|
||||
sorting_pref[j] = Utils.deepcopy(sorting_pref[j-1]) --deepcopy just as I'm slightly unsure about references here
|
||||
end
|
||||
end
|
||||
sorting_pref[1] = {column = element_to_column[name], method = new_method}
|
||||
|
||||
score_gui({player = player, frame = frame})
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_joined_game(event)
|
||||
local player = game.players[event.player_index]
|
||||
if player.index and this.sort_by and (not this.sort_by[player.index]) then
|
||||
this.sort_by[player.index] = {{method = 'ascending', column = 'completion_time'}, {method = 'descending', column = 'leagues_travelled'}, {method = 'descending', column = 'version'}, {method = 'descending', column = 'difficulty'}}
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_left_game(event)
|
||||
local player = game.players[event.player_index]
|
||||
if this.sort_by[player.index] then
|
||||
this.sort_by[player.index] = nil
|
||||
end
|
||||
end
|
||||
|
||||
Server.on_data_set_changed(
|
||||
score_dataset,
|
||||
function(data)
|
||||
local key
|
||||
if is_game_modded() then
|
||||
key = score_key_modded
|
||||
elseif _DEBUG then
|
||||
key = score_key_debug
|
||||
else
|
||||
key = score_key
|
||||
end
|
||||
if data.key == key then
|
||||
if data.value then
|
||||
this.score_table['player'] = data.value
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
Tabs.add_tab_to_gui({name = module_name, id = score_gui_token, admin = false, only_server_sided = false})
|
||||
|
||||
Event.on_init(on_init)
|
||||
Event.add(defines.events.on_player_left_game, on_player_left_game)
|
||||
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
||||
Event.add(Server.events.on_server_started, Public.load_in_scores)
|
||||
|
||||
return Public
|
1672
maps/pirates/interface.lua
Normal file
1672
maps/pirates/interface.lua
Normal file
File diff suppressed because it is too large
Load Diff
150
maps/pirates/locally_maintained_comfy_forks/tick_tack_trap.lua
Normal file
150
maps/pirates/locally_maintained_comfy_forks/tick_tack_trap.lua
Normal file
@ -0,0 +1,150 @@
|
||||
-- by mewmew
|
||||
-- modified by Gerkiz
|
||||
|
||||
-- this fork by thesixthroc to use forces except 'enemy'
|
||||
|
||||
local Event = require 'utils.event'
|
||||
local Global = require 'utils.global'
|
||||
|
||||
local traps = {}
|
||||
|
||||
Global.register(
|
||||
traps,
|
||||
function(t)
|
||||
traps = t
|
||||
end
|
||||
)
|
||||
|
||||
local tick_tacks = {'*tick*', '*tick*', '*tack*', '*tak*', '*tik*', '*tok*'}
|
||||
|
||||
local kaboom_weights = {
|
||||
{name = 'grenade', chance = 7},
|
||||
{name = 'cluster-grenade', chance = 1},
|
||||
{name = 'destroyer-capsule', chance = 1},
|
||||
{name = 'defender-capsule', chance = 4},
|
||||
{name = 'distractor-capsule', chance = 3},
|
||||
{name = 'poison-capsule', chance = 2},
|
||||
{name = 'explosive-uranium-cannon-projectile', chance = 3},
|
||||
{name = 'explosive-cannon-projectile', chance = 5}
|
||||
}
|
||||
|
||||
local kabooms = {}
|
||||
for _, t in pairs(kaboom_weights) do
|
||||
for _ = 1, t.chance, 1 do
|
||||
table.insert(kabooms, t.name)
|
||||
end
|
||||
end
|
||||
|
||||
local function create_flying_text(surface, position, text)
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'flying-text',
|
||||
position = position,
|
||||
text = text,
|
||||
color = {r = 0.75, g = 0.75, b = 0.75}
|
||||
}
|
||||
)
|
||||
if text == '...' then
|
||||
return
|
||||
end
|
||||
surface.play_sound({path = 'utility/armor_insert', position = position, volume_modifier = 0.75})
|
||||
end
|
||||
|
||||
local function create_kaboom(force_name, surface, position, name)
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
local target = position
|
||||
local speed = 0.5
|
||||
if name == 'defender-capsule' or name == 'destroyer-capsule' or name == 'distractor-capsule' then
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'flying-text',
|
||||
position = position,
|
||||
text = '(((Sentries Engaging Target)))',
|
||||
color = {r = 0.8, g = 0.0, b = 0.0}
|
||||
}
|
||||
)
|
||||
local nearest_player_unit = surface.find_nearest_enemy({position = position, max_distance = 128, force = force_name})
|
||||
if nearest_player_unit then
|
||||
target = nearest_player_unit.position
|
||||
end
|
||||
speed = 0.001
|
||||
end
|
||||
surface.create_entity(
|
||||
{
|
||||
name = name,
|
||||
position = position,
|
||||
force = force_name,
|
||||
target = target,
|
||||
speed = speed
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local function tick_tack_trap(force_name, surface, position)
|
||||
if not surface then
|
||||
return
|
||||
end
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
if not position then
|
||||
return
|
||||
end
|
||||
if not position.x then
|
||||
return
|
||||
end
|
||||
if not position.y then
|
||||
return
|
||||
end
|
||||
local tick_tack_count = math.random(5, 9)
|
||||
for t = 60, tick_tack_count * 60, 60 do
|
||||
local tick = game.tick - (game.tick % 10) + t
|
||||
if not traps[tick] then
|
||||
traps[tick] = {}
|
||||
end
|
||||
|
||||
if t < tick_tack_count * 60 then
|
||||
traps[tick][#traps[tick] + 1] = {
|
||||
callback = 'create_flying_text',
|
||||
params = {surface, {x = position.x, y = position.y}, tick_tacks[math.random(1, #tick_tacks)]}
|
||||
}
|
||||
else
|
||||
if math.random(1, 10) == 1 then
|
||||
traps[tick][#traps[tick] + 1] = {
|
||||
callback = 'create_flying_text',
|
||||
params = {surface, {x = position.x, y = position.y}, '...'}
|
||||
}
|
||||
else
|
||||
traps[tick][#traps[tick] + 1] = {
|
||||
callback = 'create_kaboom',
|
||||
params = {force_name, surface, {x = position.x, y = position.y}, kabooms[math.random(1, #kabooms)]}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_tick()
|
||||
if not traps[game.tick] then
|
||||
return
|
||||
end
|
||||
for _, token in pairs(traps[game.tick]) do
|
||||
local callback = token.callback
|
||||
local params = token.params
|
||||
if callback == 'create_kaboom' then
|
||||
create_kaboom(params[1], params[2], params[3], params[4])
|
||||
elseif callback == 'create_flying_text' then
|
||||
create_flying_text(params[1], params[2], params[3])
|
||||
end
|
||||
end
|
||||
traps[game.tick] = nil
|
||||
end
|
||||
|
||||
Event.on_nth_tick(10, on_tick)
|
||||
|
||||
return tick_tack_trap
|
446
maps/pirates/loot.lua
Normal file
446
maps/pirates/loot.lua
Normal file
@ -0,0 +1,446 @@
|
||||
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local CoreData = require 'maps.pirates.coredata'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.buried_treasure_loot_data_raw = {
|
||||
{100, 0, 1, false, 'coin', 1, 600},
|
||||
{50, 0, 1, false, 'steel-plate', 100, 150},
|
||||
{50, 0, 1, false, 'defender-capsule', 5, 18},
|
||||
{25, 0, 1, false, 'distractor-capsule', 5, 18},
|
||||
{10, 0, 1, false, 'destroyer-capsule', 3, 8},
|
||||
-- {20, 0, 1, false, 'flying-robot-frame', 20, 35},
|
||||
{40, 0, 1, false, 'construction-robot', 15, 25},
|
||||
-- {100, 0, 1, false, 'electronic-circuit', 150, 250},
|
||||
{70, 0, 1, false, 'advanced-circuit', 20, 40},
|
||||
{150, 0, 1, false, 'crude-oil-barrel', 25, 45},
|
||||
{70, 0, 1, false, 'effectivity-module-3', 3, 4},
|
||||
{70, 0, 1, false, 'speed-module-3', 3, 4},
|
||||
{10, 0, 1, false, 'productivity-module-2', 2, 2}, --3s are banned because of game mech
|
||||
{70, 0, 1, false, 'plastic-bar', 40, 70},
|
||||
{60, 0, 1, false, 'chemical-science-pack', 12, 24},
|
||||
{70, 0, 1, false, 'assembling-machine-3', 2, 2},
|
||||
{65, 0, 1, false, 'solar-panel', 7, 8},
|
||||
{20, 0, 1, false, 'radar', 10, 20},
|
||||
{10, 0, 1, false, 'production-science-pack', 12, 24},
|
||||
{10, 0, 1, false, 'utility-science-pack', 4, 4},
|
||||
{5, 0, 1, false, 'modular-armor', 1, 1},
|
||||
{5, 0, 1, false, 'laser-turret', 1, 1},
|
||||
{5, 0, 1, false, 'cannon-shell', 5, 10},
|
||||
{50, 0, 1, false, 'artillery-shell', 4, 8},
|
||||
{50, 0, 1, false, 'express-transport-belt', 8, 20},
|
||||
{35, 0, 1, false, 'express-underground-belt', 4, 4},
|
||||
{35, 0, 1, false, 'express-splitter', 4, 11},
|
||||
{50, 0, 1, false, 'stack-inserter', 4, 12},
|
||||
{0.1, 0, 1, false, 'atomic-bomb', 1, 1},
|
||||
}
|
||||
|
||||
Public.chest_loot_data_raw = {
|
||||
{80, 0, 1, false, 'coin', 250, 400},
|
||||
{30, 0, 1, false, 'rail-signal', 25, 110},
|
||||
{1, 0.2, 1, false, 'electric-engine-unit', 1, 2},
|
||||
{3, 0, 1, false, 'small-lamp', 4, 16},
|
||||
{10, 0, 1, false, 'coal', 60, 100},
|
||||
{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},
|
||||
{0.25, 0, 0.5, false, 'uranium-238', 5, 8},
|
||||
|
||||
{8, 0, 1.2, true, 'steel-chest', 4, 12},
|
||||
{2, 0, 0.8, false, 'empty-barrel', 1, 10},
|
||||
|
||||
{5, -0.2, 0.8, true, 'iron-gear-wheel', 20, 80},
|
||||
{5, -0.2, 0.8, true, 'copper-cable', 30, 100},
|
||||
-- {5, -0.2, 0.8, true, 'electronic-circuit', 15, 60},
|
||||
{2, 0.3, 1, true, 'rocket-fuel', 1, 5},
|
||||
{1, 0.2, 1.2, true, 'battery', 10, 30},
|
||||
{4, 0.2, 1.4, true, 'advanced-circuit', 10, 40},
|
||||
|
||||
{8, -0.3, 0.3, true, 'small-electric-pole', 16, 30},
|
||||
{30, 0, 1, false, 'medium-electric-pole', 2, 10},
|
||||
{3, 0.2, 1.4, true, 'big-electric-pole', 4, 8},
|
||||
{1, 0.2, 1.8, true, 'substation', 1, 3},
|
||||
{5, 0, 1.2, true, 'accumulator', 1, 4},
|
||||
{10, 0, 1, false, 'solar-panel', 2, 3},
|
||||
|
||||
{15, -0.6, 0.6, true, 'transport-belt', 20, 60},
|
||||
{10, 0, 1, false, 'fast-transport-belt', 8, 40},
|
||||
{3, 0.2, 1.8, true, 'express-transport-belt', 5, 12},
|
||||
{12, -1, 0.5, true, 'splitter', 4, 10},
|
||||
{8, 0, 1, false, 'fast-splitter', 2, 5},
|
||||
{5, 0, 2, true, 'express-splitter', 1, 3},
|
||||
{5, -1, 0.5, true, 'underground-belt', 6, 6},
|
||||
{2, 0, 1, false, 'fast-underground-belt', 6, 6},
|
||||
{3, 0, 2, true, 'express-underground-belt', 4, 4},
|
||||
|
||||
{0.5, 0, 0.1, false, 'loader', 1, 1},
|
||||
{0.5, 0.1, 0.5, false, 'fast-loader', 1, 1},
|
||||
{0.5, 0.5, 1, false, 'express-loader', 1, 1},
|
||||
|
||||
{4, -0.3, 0.3, true, 'inserter', 8, 20},
|
||||
{4, 0, 1, true, 'fast-inserter', 2, 12},
|
||||
{3, 0, 1, false, 'filter-inserter', 2, 9},
|
||||
{3, 0, 1, false, 'long-handed-inserter', 4, 16},
|
||||
{3, 0, 0.5, false, 'stack-inserter', 1, 4},
|
||||
{3, 0.5, 1, false, 'stack-inserter', 5, 8},
|
||||
{1, 0, 0.5, false, 'stack-filter-inserter', 1, 4},
|
||||
{1, 0.5, 1, false, 'stack-filter-inserter', 5, 8},
|
||||
|
||||
{40, -0.5, 0.5, true, 'firearm-magazine', 10, 32},
|
||||
{60, -1, 1, true, 'piercing-rounds-magazine', 8, 16},
|
||||
{10, 0, 1, false, 'uranium-rounds-magazine', 3, 7},
|
||||
|
||||
{1, -0.3, 0.3, true, 'assembling-machine-1', 2, 4},
|
||||
{20, 0, 0.9, false, 'assembling-machine-2', 1, 3},
|
||||
{2, 0, 1, false, 'electric-mining-drill', 2, 4},
|
||||
{3, 0.25, 1.75, true, 'assembling-machine-3', 2, 4},
|
||||
{5, 0, 1, true, 'steel-furnace', 4, 8},
|
||||
{4, 0, 2, true, 'electric-furnace', 1, 3},
|
||||
{3, 0.2, 1, true, 'chemical-plant', 1, 3},
|
||||
|
||||
{50, -1, 0.5, true, 'speed-module', 1, 3},
|
||||
{25, 0, 1.5, true, 'speed-module-2', 1, 2},
|
||||
{12, 0, 2, true, 'speed-module-3', 1, 1},
|
||||
{4, -1, 1, true, 'effectivity-module', 1, 3},
|
||||
-- {4, 0, 1, true, 'effectivity-module-2', 1, 3}, --disabled to reduce 'avalanche of crap' effect
|
||||
{4, 0, 2, true, 'effectivity-module-3', 1, 1},
|
||||
{3, 0, 1, false, 'productivity-module', 1, 1}, --not many of these, merely to make them availabile for future features
|
||||
|
||||
{4, 0, 0.1, false, 'light-armor', 1, 1},
|
||||
{2, 0, 0.5, true, 'heavy-armor', 1, 1},
|
||||
{2, 0, 0.1, false, 'submachine-gun', 1, 1},
|
||||
{1, 0, 1, false, 'gun-turret', 2, 4},
|
||||
{6, 0, 1, false, 'grenade', 2, 12},
|
||||
{4, 0, 1, false, 'stone-wall', 12, 50},
|
||||
{2, 0, 2, true, 'rocket-launcher', 1, 1},
|
||||
{4, 0, 2, true, 'rocket', 4, 10},
|
||||
{5, 0.2, 1.8, true, 'explosive-rocket', 2, 8},
|
||||
{0.2, 0, 1, false, 'poison-capsule', 2, 5},
|
||||
{0.2, 0, 1, false, 'slowdown-capsule', 2, 5},
|
||||
{0.2, 0, 1, false, 'defender-capsule', 2, 4},
|
||||
{0.15, 0, 1, false, 'distractor-capsule', 2, 4},
|
||||
{0.1, 0, 1, false, 'destroyer-capsule', 2, 2},
|
||||
{10, 0.2, 1.2, true, 'piercing-shotgun-shell', 6, 9},
|
||||
{2, 0.3, 1.2, true, 'combat-shotgun', 1, 1},
|
||||
{5, 0.2, 1.8, true, 'cluster-grenade', 8, 16},
|
||||
|
||||
{0.04, 0.25, 1.75, true, 'modular-armor', 1, 1},
|
||||
{0.01, 0.5, 1.5, true, 'power-armor', 1, 1},
|
||||
{0.3, 0.1, 1, true, 'solar-panel-equipment', 1, 2},
|
||||
{0.2, 0.1, 1, true, 'battery-equipment', 1, 1},
|
||||
{0.16, 0.2, 1, true, 'energy-shield-equipment', 1, 2},
|
||||
{0.08, 0.1, 1, true, 'night-vision-equipment', 1, 1},
|
||||
{0.04, 0.5, 1.5, true, 'personal-laser-defense-equipment', 1, 1},
|
||||
|
||||
{8, -0.5, 0.5, true, 'automation-science-pack', 4, 24},
|
||||
{8, -0.6, 0.6, true, 'logistic-science-pack', 4, 24},
|
||||
{6, -0.1, 1, true, 'military-science-pack', 8, 20},
|
||||
{6, -0.5, 1.5, true, 'chemical-science-pack', 8, 16},
|
||||
{6, 0, 1.5, true, 'production-science-pack', 8, 16},
|
||||
{6, 0, 2, true, 'utility-science-pack', 3, 3},
|
||||
|
||||
{0.5, 0.2, 1.4, true, 'construction-robot', 5, 15},
|
||||
{2, 0.5, 1.5, true, 'roboport', 1, 1},
|
||||
{2, 0.5, 1.5, false, 'logistic-chest-passive-provider', 2, 2},
|
||||
{2, 0.5, 1.5, false, 'logistic-robot', 5, 15},
|
||||
|
||||
{4, 0.2, 1.2, true, 'lubricant-barrel', 1, 4},
|
||||
|
||||
-- copying over most of those i made for chronotrain:
|
||||
--always there (or normally always there):
|
||||
-- {4, 0, 1, false, 'gate', 14, 32}, --can beat biters with them
|
||||
-- {1, 0, 1, false, 'radar', 1, 2}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {0.25, 0, 1, false, 'rail', 50, 100},
|
||||
-- {0.25, 0, 1, false, 'uranium-rounds-magazine', 1, 4},
|
||||
-- {1, 0.15, 1, false, 'pump', 1, 2}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {2, 0.15, 1, false, 'pumpjack', 1, 3}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {0.02, 0.15, 1, false, 'oil-refinery', 1, 2}, --disabled to reduce 'avalanche of crap' effect
|
||||
--shotgun meta:
|
||||
-- {10, -0.2, 0.4, true, 'shotgun-shell', 12, 24}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {5, 0, 0.4, true, 'shotgun', 1, 1}, --disabled to reduce 'avalanche of crap' effect
|
||||
--modular armor meta:
|
||||
-- {0.5, -1,3, true, "power-armor-mk2", 1, 1},
|
||||
--loader meta:
|
||||
--science meta:
|
||||
-- {4, 0.4, 1.5, true, 'utility-science-pack', 16, 32},
|
||||
-- {10, 0.5, 1.5, true, 'space-science-pack', 16, 32},
|
||||
|
||||
--early-game:
|
||||
--{3, -0.1, 0.2, false, "railgun-dart", 2, 4},
|
||||
-- {3, -0.1, 0.1, true, 'wooden-chest', 8, 40},
|
||||
-- {5, -0.1, 0.1, true, 'burner-inserter', 8, 20}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {1, -0.2, 0.2, true, 'offshore-pump', 1, 3}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {3, -0.2, 0.2, true, 'boiler', 3, 6}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {3, 0, 0.1, true, 'lab', 1, 3}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {3, -0.2, 0.2, true, 'steam-engine', 2, 4}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {3, -0.2, 0.2, true, 'burner-mining-drill', 2, 4},
|
||||
-- {3, 0, 0.3, true, 'iron-chest', 8, 40}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {6, -0.4, 0.4, true, 'stone-furnace', 8, 16}, --disabled to reduce 'avalanche of crap' effect
|
||||
--mid-game:
|
||||
--{6, 0.2, 0.5, false, "railgun-dart", 4, 8},
|
||||
-- {5, -0.2, 0.7, true, 'pipe', 30, 50}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {1, -0.2, 0.7, true, 'pipe-to-ground', 4, 8}, --disabled to reduce 'avalanche of crap' effect
|
||||
-- {3, 0, 0.7, true, 'steel-plate', 15, 80},
|
||||
-- {8, 0, 0.9, true, 'piercing-rounds-magazine', 10, 64},
|
||||
-- {4, 0.2, 0.6, true, 'engine-unit', 8, 16},
|
||||
--late-game:
|
||||
--{9, 0.5, 0.8, false, "railgun-dart", 8, 16},
|
||||
-- {5, 0, 1.2, true, 'land-mine', 16, 32},
|
||||
-- {5, 0.4, 0.7, true, 'cannon-shell', 16, 32},
|
||||
-- {5, 0.4, 0.8, true, 'explosive-cannon-shell', 16, 32},
|
||||
-- {2, 0.25, 1.75, true, 'logistic-robot', 5, 25},
|
||||
-- {1, 0.25, 1.75, true, 'laser-turret', 1, 1},
|
||||
-- {4, 0.4, 1.6, true, 'processing-unit', 30, 200},
|
||||
-- super late-game:
|
||||
--{9, 0.8, 1.2, false, "railgun-dart", 12, 20},
|
||||
-- {1, 0.9, 1.1, true, 'power-armor-mk2', 1, 1},
|
||||
-- {1, 0.8, 1.2, true, 'fusion-reactor-equipment', 1, 1}
|
||||
|
||||
--{2, 0, 1, , "computer", 1, 1},
|
||||
--{1, 0.2, 1, , "railgun", 1, 1},
|
||||
--{1, 0.9, 1, , "personal-roboport-mk2-equipment", 1, 1},
|
||||
}
|
||||
|
||||
function Public.wooden_chest_loot()
|
||||
local num = 1
|
||||
|
||||
return Public.chest_loot(num,
|
||||
Math.max(0,Math.min(1, Math.sloped(Common.difficulty(),1/2) * Common.game_completion_progress())) --enforce 0 to 1
|
||||
)
|
||||
end
|
||||
|
||||
function Public.iron_chest_loot()
|
||||
local num = 2
|
||||
|
||||
local loot = Public.chest_loot(num,
|
||||
Math.max(0,Math.min(1, Math.sloped(Common.difficulty(),1/2) * (5/100 + Common.game_completion_progress()))) --enforce 0 to 1
|
||||
) --reward higher difficulties with better loot
|
||||
loot[#loot + 1] = {name = 'coin', count = Math.random(1,1500)}
|
||||
|
||||
return loot
|
||||
end
|
||||
|
||||
function Public.covered_wooden_chest_loot()
|
||||
local num = 2
|
||||
|
||||
local loot = Public.chest_loot(num,
|
||||
Math.max(0,Math.min(1, Math.sloped(Common.difficulty(),1/2) * (10/100 + Common.game_completion_progress()))) --enforce 0 to 1
|
||||
) --reward higher difficulties with better loot
|
||||
|
||||
return loot
|
||||
end
|
||||
|
||||
function Public.stone_furnace_loot()
|
||||
return {
|
||||
{name = 'coal', count = 50},
|
||||
}
|
||||
end
|
||||
function Public.storage_tank_fluid_loot(force_type)
|
||||
local ret
|
||||
local rng = Math.random(10)
|
||||
if force_type == 'crude-oil' then
|
||||
ret = {name = 'crude-oil', amount = Math.random(3000, 12500)}
|
||||
elseif force_type == 'petroleum-gas' then
|
||||
ret = {name = 'petroleum-gas', amount = Math.random(1500, 7500)}
|
||||
elseif rng < 6 then
|
||||
ret = {name = 'crude-oil', amount = Math.random(1500, 4500)}
|
||||
elseif rng == 7 then
|
||||
ret = {name = 'light-oil', amount = Math.random(1500, 3500)}
|
||||
elseif rng == 8 then
|
||||
ret = {name = 'heavy-oil', amount = Math.random(1500, 3500)}
|
||||
-- elseif rng == 9 then
|
||||
-- ret = {name = 'lubricant', amount = Math.random(1000, 2000)}
|
||||
else
|
||||
ret = {name = 'petroleum-gas', amount = Math.random(1500, 2000)}
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function Public.swamp_storage_tank_fluid_loot()
|
||||
local ret
|
||||
ret = {name = 'sulfuric-acid', amount = Math.random(500, 1500)}
|
||||
return ret
|
||||
end
|
||||
|
||||
function Public.roboport_bots_loot()
|
||||
return {
|
||||
{name = 'logistic-robot', count = 5},
|
||||
}
|
||||
-- construction robots
|
||||
end
|
||||
|
||||
function Public.random_plates(multiplier)
|
||||
multiplier = multiplier or 1
|
||||
local platesrng = Math.random(5)
|
||||
if platesrng <= 2 then
|
||||
return {name = 'iron-plate', count = 120 * multiplier}
|
||||
elseif platesrng <= 4 then
|
||||
return {name = 'copper-plate', count = 120 * multiplier}
|
||||
else
|
||||
return {name = 'steel-plate', count = 20 * multiplier}
|
||||
end
|
||||
end
|
||||
|
||||
function Public.chest_loot(number_of_items, game_completion_progress)
|
||||
local ret = Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.chest_loot_data_raw), number_of_items, game_completion_progress)
|
||||
|
||||
ret[#ret + 1] = ret[1]
|
||||
ret[1] = Public.random_plates()
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function Public.buried_treasure_loot()
|
||||
local ret = Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.buried_treasure_loot_data_raw), 1, Math.sloped(Common.difficulty(),1/2) * Common.game_completion_progress_capped())
|
||||
|
||||
if ret and ret[1] then return ret[1] end
|
||||
end
|
||||
|
||||
function Public.maze_camp_loot()
|
||||
if Math.random(10) <= 7 then
|
||||
return {Public.random_plates()}
|
||||
else
|
||||
return Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.chest_loot_data_raw), 1, Math.max(0,Math.min(1, Math.sloped(Common.difficulty(),1/2) * (15/100 + Common.game_completion_progress()))))
|
||||
end
|
||||
end
|
||||
|
||||
Public.maze_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},
|
||||
{6, -0.5, 1.5, true, 'chemical-science-pack', 4, 12},
|
||||
{6, 0, 1.5, true, 'production-science-pack', 3, 11},
|
||||
{2, 0, 2, true, 'utility-science-pack', 2, 3},
|
||||
-- {4, 0.4, 1.5, true, 'utility-science-pack', 16, 32},
|
||||
-- {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.max(0,Math.min(1, Math.sloped(Common.difficulty(),1/2) * (Common.game_completion_progress()))))
|
||||
end
|
||||
|
||||
Public.maze_treasure_data_raw = {
|
||||
{2, -1, 1, true, 'rocket', 18, 24},
|
||||
{2, -0.8, 0.8, false, 'stack-inserter', 8, 10},
|
||||
{2, -0.8, 0.8, false, 'stack-filter-inserter', 5, 6},
|
||||
{2, 0, 1, false, 'poison-capsule', 22, 22},
|
||||
{2, 0, 1, false, 'destroyer-capsule', 8, 8},
|
||||
{2, 0, 1, false, 'slowdown-capsule', 14, 14},
|
||||
|
||||
{2, 0, 1, false, 'uranium-rounds-magazine', 15, 25},
|
||||
{2, 0, 1, false, 'artillery-shell', 5, 7},
|
||||
{2, 0, 1, false, 'rail-signal', 400, 500},
|
||||
{2, 0, 1, false, 'electric-engine-unit', 3, 4},
|
||||
{2, 0, 1, false, 'cluster-grenade', 8, 12},
|
||||
|
||||
{0.5, 0, 1, false, 'nuclear-fuel', 1, 1},
|
||||
|
||||
{1, 0, 0.8, false, 'speed-module-3', 2, 2},
|
||||
{1, 0, 0.8, false, 'effectivity-module-3', 3, 3},
|
||||
{0.5, 0, 1, false, 'productivity-module-2', 2, 2}, --3s are banned because of game mech
|
||||
|
||||
{2, 0, 1.5, true, 'production-science-pack', 20, 25},
|
||||
{2, 0, 2, true, 'utility-science-pack', 7, 8},
|
||||
{2, 0, 1.5, true, 'coin', 3000, 6500},
|
||||
{3, 0, 0.9, false, 'beacon', 1, 1},
|
||||
|
||||
{1, 0, 1, false, 'construction-robot', 30, 40},
|
||||
{3, 0, 1, false, 'logistic-chest-passive-provider', 2, 2},
|
||||
|
||||
{1, 0.2, 1.8, true, 'explosive-rocket', 6, 8},
|
||||
|
||||
{1, 0, 0.9, false, 'express-transport-belt', 20, 60},
|
||||
{0.5, 0, 0.9, false, 'express-underground-belt', 6, 6},
|
||||
{0.5, 0, 0.9, false, 'express-splitter', 10, 10},
|
||||
{1, 0, 0.9, false, 'express-loader', 2, 2},
|
||||
{0.5, 0, 0.5, false, 'substation', 2, 2},
|
||||
{0.5, 0, 0.8, false, 'assembling-machine-3', 3, 3},
|
||||
{1, 0, 0.7, false, 'electric-furnace', 4, 6},
|
||||
|
||||
{1, 0, 0.8, false, 'modular-armor', 1, 1},
|
||||
{1, 0, 2, true, 'power-armor', 1, 1},
|
||||
{0.1, 0, 2, true, 'power-armor-mk2', 1, 1},
|
||||
|
||||
{2, -1, 1, true, 'solar-panel-equipment', 3, 4},
|
||||
{2, -1, 1, true, 'battery-equipment', 1, 1},
|
||||
{1, 0, 2, true, 'battery-mk2-equipment', 1, 1},
|
||||
{2, -1, 1, true, 'energy-shield-equipment', 1, 2},
|
||||
{1, 0, 2, true, 'energy-shield-mk2-equipment', 1, 1},
|
||||
{1, -1, 1, true, 'personal-roboport-equipment', 1, 1},
|
||||
{0.5, 0, 2, true, 'personal-roboport-mk2-equipment', 1, 1},
|
||||
{0.5, 0, 0.8, false, 'night-vision-equipment', 1, 1},
|
||||
{1, 0, 1, false, 'personal-laser-defense-equipment', 1, 1},
|
||||
{0.5, 0, 1, false, 'fusion-reactor-equipment', 1, 1},
|
||||
{2, 0, 1, false, 'exoskeleton-equipment', 1, 1},
|
||||
|
||||
{2, -0.7, 1.3, true, 'advanced-circuit', 40, 90},
|
||||
|
||||
{2, 0, 0.5, false, 'laser-turret', 1, 2},
|
||||
{2, 0.6, 1, false, 'laser-turret', 4, 5},
|
||||
{1, 0, 0.5, false, 'roboport', 1, 1},
|
||||
|
||||
{1, 0, 1, false, 'atomic-bomb', 1, 1},
|
||||
}
|
||||
|
||||
function Public.maze_treasure_loot()
|
||||
if Math.random(5) == 1 then
|
||||
return {Public.random_plates(8)}
|
||||
else
|
||||
return Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.maze_treasure_data_raw), 1, Math.max(0,Math.min(1, Math.sloped(Common.difficulty(),1/2) * (Common.game_completion_progress()))))
|
||||
end
|
||||
end
|
||||
|
||||
Public.dredger_loot_raw = {
|
||||
{8, 0, 1, false, 'iron-plate', 1, 1},
|
||||
{8, 0, 1, false, 'copper-plate', 1, 1},
|
||||
{8, 0, 1, false, 'coal', 1, 1},
|
||||
{10, 0, 1, false, 'coin', 1, 1},
|
||||
|
||||
{2, 0, 1, false, 'small-electric-pole', 1, 1},
|
||||
{1, 0, 1, false, 'medium-electric-pole', 1, 1},
|
||||
{0.1, 0, 1, false, 'big-electric-pole', 1, 1},
|
||||
|
||||
{0.2, 0, 1, false, 'poison-capsule', 1, 1},
|
||||
{0.2, 0, 1, false, 'slowdown-capsule', 1, 1},
|
||||
{0.1, 0, 1, false, 'destroyer-capsule', 1, 1},
|
||||
{0.2, 0, 1, false, 'defender-capsule', 1, 1},
|
||||
{0.2, 0, 1, false, 'distractor-capsule', 1, 1},
|
||||
|
||||
|
||||
{0.05, 0, 1, false, 'speed-module-3', 1, 1},
|
||||
{0.05, 0, 1, false, 'effectivity-module-3', 1, 1},
|
||||
{0.05, 0, 1, false, 'productivity-module-2', 1, 1}, --3s are banned because of game mech
|
||||
|
||||
{0.1, 0, 1, false, 'rocket', 1, 1},
|
||||
{0.01, 0, 1, false, 'explosive-rocket', 1, 1},
|
||||
|
||||
{4, 0, 1, false, 'automation-science-pack', 1, 1},
|
||||
{4, 0, 1, false, 'logistic-science-pack', 1, 1},
|
||||
{2, 0, 1, false, 'military-science-pack', 1, 1},
|
||||
{1, 0, 1, false, 'chemical-science-pack', 1, 1},
|
||||
{1, 0, 1, false, 'production-science-pack', 1, 1},
|
||||
{0.5, 0, 1, false, 'utility-science-pack', 1, 1},
|
||||
|
||||
{0.012, 0, 0.8, false, 'night-vision-equipment', 1, 1},
|
||||
{0.01, 0, 1, false, 'exoskeleton-equipment', 1, 1},
|
||||
{0.01, -1, 1, true, 'energy-shield-equipment', 1, 1},
|
||||
{0.01, -1, 1, true, 'solar-panel-equipment', 1, 1},
|
||||
{0.01, -1, 1, true, 'battery-equipment', 1, 1},
|
||||
{0.008, 0, 2, true, 'battery-mk2-equipment', 1, 1},
|
||||
{0.008, 0, 1, false, 'personal-laser-defense-equipment', 1, 1},
|
||||
{0.008, 0, 2, true, 'energy-shield-mk2-equipment', 1, 1},
|
||||
{0.008, -1, 1, true, 'personal-roboport-equipment', 1, 1},
|
||||
{0.004, 0, 1, false, 'fusion-reactor-equipment', 1, 1},
|
||||
{0.004, 0, 2, true, 'personal-roboport-mk2-equipment', 1, 1},
|
||||
}
|
||||
|
||||
function Public.dredger_loot()
|
||||
return Common.raffle_from_processed_loot_data(Common.processed_loot_data(Public.dredger_loot_raw), 1, Math.max(0,Math.min(1, Common.game_completion_progress())))
|
||||
end
|
||||
|
||||
return Public
|
396
maps/pirates/main.lua
Normal file
396
maps/pirates/main.lua
Normal file
@ -0,0 +1,396 @@
|
||||
|
||||
--[[
|
||||
Pirate Ship is maintained by thesixthroc and hosted by Comfy.
|
||||
Want to host it? Ask us at getcomfy.eu/discord!
|
||||
]]
|
||||
--[[
|
||||
|
||||
== Tips for Developers! ==
|
||||
|
||||
The scenario is quite complex, but there are ways to get started, even if you don't know much Lua. Some ideas (incomplete):
|
||||
|
||||
• Go to pirates/surfaces/islands/first and edit stuff there to see the effect it has on the first island
|
||||
• Ask thesixthroc for access to the ToDo list on Github Projects, to see what needs doing
|
||||
]]
|
||||
|
||||
--[[personal note for thesixthroc in XX years: my design notes are all in Obsidian (edit: mostly moved to Github Projects)]]
|
||||
|
||||
|
||||
-- require 'modules.biters_yield_coins'
|
||||
require 'modules.biter_noms_you'
|
||||
require 'modules.no_deconstruction_of_neutral_entities'
|
||||
|
||||
require 'maps.pirates.custom_events' --probably do this before anything else
|
||||
|
||||
require 'utils.server'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
-- local Modifers = require 'player_modifiers'
|
||||
local BottomFrame = require 'utils.gui.bottom_frame'
|
||||
local Autostash = require 'modules.autostash'
|
||||
require 'modules.inserter_drops_pickup'
|
||||
|
||||
|
||||
local TickFunctions = require 'maps.pirates.tick_functions'
|
||||
local ClassTickFunctions = require 'maps.pirates.tick_functions_classes'
|
||||
|
||||
require 'maps.pirates.commands'
|
||||
require 'maps.pirates.math'
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
require 'maps.pirates.gui.gui'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
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 Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
local Interface = require 'maps.pirates.interface'
|
||||
require 'maps.pirates.structures.boats.boats'
|
||||
local Progression = require 'maps.pirates.progression'
|
||||
local Ai = require 'maps.pirates.ai'
|
||||
require 'maps.pirates.ores'
|
||||
require 'maps.pirates.quest'
|
||||
require 'maps.pirates.parrot'
|
||||
require 'maps.pirates.shop.shop'
|
||||
require 'maps.pirates.boat_upgrades'
|
||||
local Token = require 'utils.token'
|
||||
local Task = require 'utils.task'
|
||||
|
||||
require 'utils.profiler'
|
||||
|
||||
local Public = {}
|
||||
|
||||
-- parrot sprites from https://elthen.itch.io/2d-pixel-art-parrot-sprites, licensed appropriately
|
||||
|
||||
local jetty_delayed = Token.register(
|
||||
-- function(data)
|
||||
function()
|
||||
Surfaces.Lobby.place_lobby_jetty_and_boats()
|
||||
end
|
||||
)
|
||||
local function on_init()
|
||||
Memory.global_reset_memory()
|
||||
local global_memory = Memory.get_global_memory()
|
||||
|
||||
game.reset_time_played()
|
||||
|
||||
-- local spectator = game.create_force('spectator')
|
||||
-- local spectator_permissions = game.permissions.create_group('spectator')
|
||||
-- spectator_permissions.set_allows_action(defines.input_action.start_walking,false)
|
||||
|
||||
Autostash.insert_into_furnace(true)
|
||||
-- Autostash.insert_into_wagon(true)
|
||||
Autostash.bottom_button(true)
|
||||
BottomFrame.reset()
|
||||
BottomFrame.activate_custom_buttons(true)
|
||||
-- BottomFrame.bottom_right(true)
|
||||
|
||||
local mgs = game.surfaces['nauvis'].map_gen_settings
|
||||
mgs.width = 16
|
||||
mgs.height = 16
|
||||
game.surfaces['nauvis'].map_gen_settings = mgs
|
||||
game.surfaces['nauvis'].clear()
|
||||
|
||||
game.create_surface('piratedev1', Common.default_map_gen_settings(100, 100))
|
||||
game.surfaces['piratedev1'].clear()
|
||||
|
||||
Common.init_game_settings(Balance.technology_price_multiplier)
|
||||
|
||||
global_memory.active_crews_cap = Common.active_crews_cap
|
||||
global_memory.minimum_capacity_slider_value = Common.minimum_capacity_slider_value
|
||||
|
||||
Surfaces.Lobby.create_starting_dock_surface()
|
||||
local lobby = game.surfaces[CoreData.lobby_surface_name]
|
||||
game.forces.player.set_spawn_position(Common.lobby_spawnpoint, lobby)
|
||||
game.forces.player.character_running_speed_modifier = Balance.base_extra_character_speed
|
||||
|
||||
game.create_force('environment')
|
||||
for id = 1, 3, 1 do
|
||||
game.create_force(string.format('enemy-%03d', id))
|
||||
game.create_force(string.format('ancient-friendly-%03d', id))
|
||||
game.create_force(string.format('ancient-hostile-%03d', id))
|
||||
|
||||
local crew_force = game.create_force(string.format('crew-%03d', id))
|
||||
|
||||
Crew.reset_crew_and_enemy_force(id)
|
||||
crew_force.research_queue_enabled = true
|
||||
end
|
||||
|
||||
-- Delay.global_add(Delay.global_enum.PLACE_LOBBY_JETTY_AND_BOATS)
|
||||
Task.set_timeout_in_ticks(2, jetty_delayed, {})
|
||||
|
||||
if _DEBUG then
|
||||
game.print('Debug mode on. Use /go to get started (sometimes crashes)')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.on_init(on_init)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
local function crew_tick()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local tick = game.tick
|
||||
|
||||
TickFunctions.boat_movement_tick(5) --arguments are tick intervals
|
||||
-- TickFunctions.parrot_tick(5)
|
||||
|
||||
if tick % 10 == 0 then
|
||||
TickFunctions.prevent_disembark(10)
|
||||
TickFunctions.prevent_unbarreling_off_ship(10)
|
||||
end
|
||||
|
||||
if memory.age and memory.overworldx and memory.overworldx > 0 then
|
||||
memory.age = memory.age + 5
|
||||
end
|
||||
if memory.real_age then
|
||||
memory.real_age = memory.real_age + 5
|
||||
end
|
||||
if tick % 60 == 0 then
|
||||
TickFunctions.captain_warn_afk(60)
|
||||
end
|
||||
|
||||
if tick % Common.loading_interval == 0 then
|
||||
TickFunctions.loading_update(Common.loading_interval)
|
||||
end
|
||||
|
||||
if tick % 5 == 0 then
|
||||
TickFunctions.quest_progress_tick(5)
|
||||
end
|
||||
|
||||
if tick % 5 == 0 then
|
||||
TickFunctions.strobe_player_colors(5)
|
||||
end
|
||||
|
||||
if tick % 10 == 0 then
|
||||
TickFunctions.shop_ratelimit_tick(10)
|
||||
end
|
||||
|
||||
if tick % 30 == 0 then
|
||||
TickFunctions.silo_update(30)
|
||||
end
|
||||
|
||||
if tick % 60 == 0 then
|
||||
TickFunctions.ship_deplete_fuel(60)
|
||||
end
|
||||
|
||||
if tick % 10 == 0 then
|
||||
TickFunctions.pick_up_tick(10)
|
||||
end
|
||||
|
||||
if tick % 60 == 0 then
|
||||
if memory.boat and memory.boat.state == Structures.Boats.enum_state.ATSEA_SAILING then
|
||||
TickFunctions.crowsnest_natural_move(120)
|
||||
end
|
||||
end
|
||||
|
||||
if tick % 60 == 15 or tick % 60 == 45 then
|
||||
if memory.boat and memory.boat.state == Structures.Boats.enum_state.ATSEA_SAILING then
|
||||
TickFunctions.overworld_check_collisions(120)
|
||||
end
|
||||
end
|
||||
|
||||
if tick % 60 == 30 then
|
||||
if memory.boat and memory.boat.state == Structures.Boats.enum_state.ATSEA_SAILING then
|
||||
TickFunctions.crowsnest_steer(120)
|
||||
end
|
||||
end
|
||||
|
||||
if tick % 60 == 0 then
|
||||
TickFunctions.slower_boat_tick(60)
|
||||
end
|
||||
|
||||
if tick % 10 == 0 then
|
||||
TickFunctions.update_boat_stored_resources(10)
|
||||
end
|
||||
|
||||
if tick % 10 == 0 then
|
||||
TickFunctions.covered_requirement_check(10)
|
||||
end
|
||||
|
||||
if tick % 30 == 0 then
|
||||
TickFunctions.buried_treasure_check(30)
|
||||
end
|
||||
|
||||
if tick % 60 == 0 then
|
||||
TickFunctions.raft_raids(60)
|
||||
end
|
||||
|
||||
if tick % 60 == 0 then
|
||||
TickFunctions.place_cached_structures(60)
|
||||
end
|
||||
|
||||
if tick % 240 == 0 then
|
||||
TickFunctions.check_all_spawners_dead(240)
|
||||
end
|
||||
|
||||
if tick % 60 == 0 then
|
||||
|
||||
if destination.dynamic_data.timer then
|
||||
destination.dynamic_data.timer = destination.dynamic_data.timer + 1
|
||||
end
|
||||
|
||||
if memory.captain_acceptance_timer then
|
||||
memory.captain_acceptance_timer = memory.captain_acceptance_timer - 1
|
||||
if memory.captain_acceptance_timer == 0 then
|
||||
Roles.assign_captain_based_on_priorities()
|
||||
end
|
||||
end
|
||||
|
||||
if memory.captain_accrued_time_data and memory.playerindex_captain and memory.overworldx and memory.overworldx > 0 and memory.overworldx < CoreData.victory_x then --only count time in the 'main game'
|
||||
local player = game.players[memory.playerindex_captain]
|
||||
if player and player.name then
|
||||
if (not memory.captain_accrued_time_data[player.name]) then memory.captain_accrued_time_data[player.name] = 0 end
|
||||
memory.captain_accrued_time_data[player.name] = memory.captain_accrued_time_data[player.name] + 1
|
||||
end
|
||||
end
|
||||
|
||||
if destination.dynamic_data.time_remaining and destination.dynamic_data.time_remaining > 0 then
|
||||
destination.dynamic_data.time_remaining = destination.dynamic_data.time_remaining - 1
|
||||
|
||||
if destination.dynamic_data.time_remaining == 0 then
|
||||
if memory.boat and memory.boat.surface_name then
|
||||
local surface_name_decoded = Surfaces.SurfacesCommon.decode_surface_name(memory.boat.surface_name)
|
||||
local type = surface_name_decoded.type
|
||||
if type == Surfaces.enum.ISLAND then
|
||||
Progression.retreat_from_island(false)
|
||||
elseif type == Surfaces.enum.DOCK then
|
||||
Progression.undock_from_dock(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if tick % 240 == 0 then
|
||||
if memory.max_players_recorded then
|
||||
local count_now = #Common.crew_get_crew_members()
|
||||
if count_now and count_now > memory.max_players_recorded then
|
||||
memory.max_players_recorded = count_now
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if tick % 240 == 0 then
|
||||
TickFunctions.Kraken_Destroyed_Backup_check(240)
|
||||
end
|
||||
|
||||
if tick % 300 == 0 then
|
||||
TickFunctions.periodic_free_resources(300)
|
||||
end
|
||||
|
||||
if tick % 30 == 0 then
|
||||
ClassTickFunctions.update_character_properties(30)
|
||||
end
|
||||
|
||||
if tick % 30 == 0 then
|
||||
ClassTickFunctions.class_renderings(30)
|
||||
end
|
||||
|
||||
if tick % 120 == 0 then
|
||||
Ai.Tick_actions(120)
|
||||
end
|
||||
|
||||
if tick % 240 == 0 then
|
||||
TickFunctions.LOS_tick(240)
|
||||
end
|
||||
|
||||
if tick % 420 == 0 then
|
||||
ClassTickFunctions.class_rewards_tick(420)
|
||||
end
|
||||
|
||||
if tick % 300 == 0 then
|
||||
TickFunctions.update_recentcrewmember_list(300)
|
||||
end
|
||||
|
||||
if tick % 1800 == 0 then
|
||||
TickFunctions.transfer_pollution(1800)
|
||||
end
|
||||
|
||||
if tick % 3600 == 0 then
|
||||
TickFunctions.prune_offline_characters_list(3600)
|
||||
end
|
||||
|
||||
-- if tick % (60*60*60) == 0 then
|
||||
-- Parrot.parrot_say_tip()
|
||||
-- end
|
||||
|
||||
if memory.crew_disband_tick then
|
||||
if memory.crew_disband_tick < tick then
|
||||
memory.crew_disband_tick = nil
|
||||
Crew.disband_crew()
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function global_tick()
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local tick = game.tick
|
||||
|
||||
if tick % 60 == 0 then
|
||||
TickFunctions.update_players_second()
|
||||
end
|
||||
|
||||
if tick % 30 == 0 then
|
||||
for _, player in pairs(game.connected_players) do
|
||||
-- figure out which crew this is about:
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or 0
|
||||
Memory.set_working_id(crew_id)
|
||||
Roles.update_tags(player)
|
||||
end
|
||||
end
|
||||
|
||||
for _, id in pairs(global_memory.crew_active_ids) do
|
||||
Memory.set_working_id(id)
|
||||
|
||||
crew_tick()
|
||||
end
|
||||
|
||||
TickFunctions.update_player_guis(5)
|
||||
end
|
||||
|
||||
event.on_nth_tick(5, global_tick)
|
||||
|
||||
|
||||
local function instatick()
|
||||
local global_memory = Memory.get_global_memory()
|
||||
for _, id in pairs(global_memory.crew_active_ids) do
|
||||
Memory.set_working_id(id)
|
||||
TickFunctions.minimap_jam(1)
|
||||
TickFunctions.silo_insta_update()
|
||||
end
|
||||
end
|
||||
|
||||
event.on_nth_tick(1, instatick)
|
||||
|
||||
|
||||
|
||||
----- FOR BUGFIXING HARD CRASHES (segfaults) ------
|
||||
-- often, segfaults are due to an error during chunk generation (as of 1.1.0 or so, anyway.)
|
||||
-- to help debug, comment this out, and instead use the command /chnk to generate some chunks manually
|
||||
event.add(defines.events.on_chunk_generated, Interface.event_on_chunk_generated)
|
||||
|
||||
----- FOR DESYNC BUGFIXING -----
|
||||
local gMeta = getmetatable(_ENV)
|
||||
if not gMeta then
|
||||
gMeta = {}
|
||||
setmetatable(_ENV, gMeta)
|
||||
end
|
||||
|
||||
gMeta.__newindex = function(_, n, v)
|
||||
log('Desync warning: attempt to write to undeclared var ' .. n)
|
||||
global[n] = v
|
||||
end
|
||||
gMeta.__index = function(_, n)
|
||||
return global[n]
|
||||
end
|
||||
|
||||
return Public
|
136
maps/pirates/math.lua
Normal file
136
maps/pirates/math.lua
Normal file
File diff suppressed because one or more lines are too long
161
maps/pirates/memory.lua
Normal file
161
maps/pirates/memory.lua
Normal file
@ -0,0 +1,161 @@
|
||||
|
||||
local Global = require 'utils.global'
|
||||
-- local CoreData = require 'maps.pirates.coredata'
|
||||
local pirates_global_memory = {}
|
||||
local Public = {}
|
||||
|
||||
-- register only this
|
||||
Global.register(
|
||||
pirates_global_memory,
|
||||
function(tbl)
|
||||
pirates_global_memory = tbl
|
||||
end
|
||||
)
|
||||
|
||||
function Public.global_reset_memory()
|
||||
for k, _ in pairs(pirates_global_memory) do
|
||||
pirates_global_memory[k] = nil
|
||||
end
|
||||
|
||||
pirates_global_memory.config = {}
|
||||
pirates_global_memory.afk_player_indices = {}
|
||||
pirates_global_memory.playerindex_to_time_played_continuously = {}
|
||||
pirates_global_memory.playerindex_to_captainhood_priority = {}
|
||||
pirates_global_memory.player_gui_memories = {}
|
||||
pirates_global_memory.crew_memories = {}
|
||||
pirates_global_memory.crew_active_ids = {}
|
||||
pirates_global_memory.working_id = nil --should only ever be nil, 1, 2 or 3
|
||||
|
||||
pirates_global_memory.lobby_boats = {}
|
||||
|
||||
pirates_global_memory.active_crews_cap = nil
|
||||
pirates_global_memory.crew_capacity_min = nil
|
||||
|
||||
pirates_global_memory.crewproposals = {}
|
||||
|
||||
pirates_global_memory.global_delayed_tasks = {}
|
||||
pirates_global_memory.global_buffered_tasks = {}
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.reset_crew_memory(id) --mostly serves as a dev reference of memory entries
|
||||
-- but not _everything_ is stored here, it's just a guide to the most important things
|
||||
|
||||
pirates_global_memory.crew_memories[id] = {}
|
||||
local memory = pirates_global_memory.crew_memories[id]
|
||||
|
||||
memory.secs_id = nil
|
||||
|
||||
memory.id = nil
|
||||
memory.age = nil
|
||||
memory.real_age = nil
|
||||
memory.completion_time = nil
|
||||
|
||||
memory.force_name = nil
|
||||
memory.enemy_force_name = nil
|
||||
|
||||
memory.original_proposal = nil
|
||||
memory.name = nil
|
||||
memory.difficulty_option = nil
|
||||
memory.capacity_option = nil
|
||||
-- memory.mode_option = nil
|
||||
memory.difficulty = nil
|
||||
memory.capacity = nil
|
||||
-- memory.mode = nil
|
||||
|
||||
memory.destinations = nil
|
||||
memory.currentdestination_index = nil
|
||||
|
||||
memory.hold_surface_count = nil
|
||||
memory.merchant_ships_unlocked = nil
|
||||
|
||||
memory.boat = nil
|
||||
|
||||
memory.available_classes_pool = nil
|
||||
|
||||
memory.crewplayerindices = nil
|
||||
memory.spectatorplayerindices = nil
|
||||
memory.tempbanned_from_joining_data = nil
|
||||
memory.playerindex_captain = nil
|
||||
memory.captain_accrued_time_data = nil
|
||||
memory.max_players_recorded = nil
|
||||
memory.temporarily_logged_off_characters = nil
|
||||
|
||||
memory.speed_boost_characters = nil
|
||||
|
||||
memory.enemyboats = nil
|
||||
memory.overworld_krakens = nil
|
||||
memory.active_sea_enemies = nil
|
||||
memory.kraken_stream_registrations = nil
|
||||
|
||||
memory.mainshop_availability_bools = nil
|
||||
|
||||
memory.delayed_tasks = nil
|
||||
memory.buffered_tasks = nil
|
||||
memory.game_lost = false
|
||||
memory.game_won = false
|
||||
memory.crew_disband_tick = nil
|
||||
memory.destinationsvisited_indices = nil
|
||||
memory.overworldx = nil
|
||||
memory.overworldy = nil
|
||||
memory.mapbeingloadeddestination_index = nil
|
||||
memory.loadingticks = nil
|
||||
memory.stored_fuel = nil
|
||||
memory.spawnpoint = nil
|
||||
|
||||
memory.evolution_factor = nil
|
||||
memory.scripted_biters = nil
|
||||
memory.scripted_unit_groups = nil
|
||||
memory.floating_pollution = nil
|
||||
end
|
||||
|
||||
function Public.fallthrough_crew_memory() --could make this a metatable, but metatables and factorio global seem not to play nicely
|
||||
return {
|
||||
id = 0,
|
||||
difficulty = 1,
|
||||
force_name = 'player',
|
||||
boat = {},
|
||||
destinations = {},
|
||||
spectatorplayerindices = {},
|
||||
crewplayerindices = {},
|
||||
--[[boat = {
|
||||
type = nil,
|
||||
state = nil,
|
||||
speed = nil,
|
||||
speedticker1 = nil,
|
||||
speedticker2 = nil,
|
||||
speedticker3 = nil,
|
||||
stored_resources = {},
|
||||
position = nil, --the far right edge of the boat
|
||||
decksteeringchests = nil,
|
||||
crowsneststeeringchests = nil,
|
||||
cannons = nil,
|
||||
EEI = nil,
|
||||
EEIpower_production = nil,
|
||||
EEIelectric_buffer_size = nil,
|
||||
dockedposition = nil,
|
||||
surface_name = nil,
|
||||
}]]
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
function Public.get_crew_memory()
|
||||
if pirates_global_memory.working_id and pirates_global_memory.working_id > 0 then
|
||||
return pirates_global_memory.crew_memories[pirates_global_memory.working_id] or Public.fallthrough_crew_memory()
|
||||
else
|
||||
return Public.fallthrough_crew_memory()
|
||||
end
|
||||
end
|
||||
|
||||
function Public.get_global_memory()
|
||||
return pirates_global_memory
|
||||
end
|
||||
|
||||
function Public.set_working_id(id)
|
||||
pirates_global_memory.working_id = id
|
||||
end
|
||||
|
||||
return Public
|
29
maps/pirates/noise_pregen/noise_pregen.lua
Normal file
29
maps/pirates/noise_pregen/noise_pregen.lua
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.encoding = [[!#$%&'()*+'-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ/^_`abcdefghijklmnopqrstuvwxyz{}|~]]
|
||||
Public.encoding_length = 91
|
||||
Public.enc = {}
|
||||
Public.dec = {}
|
||||
for i=1,Public.encoding_length do
|
||||
Public.enc[i]=Public.encoding:sub(i,i)
|
||||
Public.dec[Public.encoding:sub(i,i)]=i
|
||||
end
|
||||
|
||||
Public.island1 = {}
|
||||
Public.island1.Data = require 'maps.pirates.noise_pregen.perlinwavelength100boxsize1000octaves5gain0p8lacunity2lengthpower1rms0p05423'
|
||||
Public.island1.upperscale = 100
|
||||
Public.island1.boxsize = 1000
|
||||
Public.island1.wordlength = 5
|
||||
Public.island1.factor = 0.1925/0.05423
|
||||
|
||||
Public.forest1 = {}
|
||||
Public.forest1.Data = require 'maps.pirates.noise_pregen.simplexwavelength100boxsize1000octaves5gain0p65lacunity2lengthpower1p2rms0p06243'
|
||||
Public.forest1.upperscale = 100
|
||||
Public.forest1.boxsize = 1000
|
||||
Public.forest1.wordlength = 5
|
||||
Public.forest1.factor = 0.1925/0.06243
|
||||
|
||||
|
||||
|
||||
return Public
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
208
maps/pirates/ores.lua
Normal file
208
maps/pirates/ores.lua
Normal file
@ -0,0 +1,208 @@
|
||||
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Common = require 'maps.pirates.common'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
local simplex_noise = require 'utils.simplex_noise'.d2
|
||||
-- local CustomEvents = require 'maps.pirates.custom_events'
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
||||
|
||||
function Public.try_ore_spawn(surface, realp, source_name, density_bonus)
|
||||
density_bonus = density_bonus or 0
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local choices = destination.dynamic_data.hidden_ore_remaining_abstract
|
||||
|
||||
local ret = false
|
||||
|
||||
if choices and Utils.length(choices) > 0 then
|
||||
local choices_possible = {}
|
||||
local choices_to_prioitise = {}
|
||||
|
||||
for k, v in pairs(choices) do
|
||||
if v>0 then choices_possible[k] = v end
|
||||
|
||||
if (not destination.dynamic_data.ore_types_spawned[k]) then
|
||||
choices_to_prioitise[#choices_to_prioitise + 1] = k
|
||||
end
|
||||
end
|
||||
|
||||
if Utils.length(choices_possible) > 0 then
|
||||
local choice
|
||||
if Utils.length(choices_to_prioitise) > 0 then
|
||||
choice = choices_to_prioitise[Math.random(Utils.length(choices_to_prioitise))]
|
||||
else
|
||||
choice = Math.raffle2(choices_possible)
|
||||
end
|
||||
|
||||
local placed
|
||||
if choice == 'crude-oil' then
|
||||
|
||||
placed = Common.oil_abstract_to_real(6 + 0.7*choices[choice]/(Math.max(1, Math.ceil((choices[choice]/4)^(1/2))))) * (0.8 + 0.4 * Math.random()) --thesixthroc's magic function, just plot this to see that it makes sense
|
||||
|
||||
placed = Math.min(placed, Common.oil_abstract_to_real(choices[choice]))
|
||||
|
||||
local tile = surface.get_tile(realp)
|
||||
if (not (tile and tile.name and Utils.contains(CoreData.tiles_that_conflict_with_resource_layer_extended, tile.name))) then
|
||||
surface.create_entity{name = 'crude-oil', amount = placed, position = realp}
|
||||
else
|
||||
placed = 0
|
||||
end
|
||||
|
||||
if placed then
|
||||
choices[choice] = Math.max(0, choices[choice] - Common.oil_real_to_abstract(placed))
|
||||
if placed > 0 and not destination.dynamic_data.ore_types_spawned[choice] then
|
||||
destination.dynamic_data.ore_types_spawned[choice] = true
|
||||
end
|
||||
ret = true
|
||||
end
|
||||
else
|
||||
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
|
||||
|
||||
local radius_squared = (destination.static_params and destination.static_params.radius_squared_modifier or 1) * (12 + 45 * Math.slopefromto(Common.ore_abstract_to_real(choices[choice]), 800, 20000)) * (0.6 + Math.random()) --tuned
|
||||
|
||||
if source_name == 'rock-huge' then
|
||||
radius_squared = radius_squared * 1.5
|
||||
end
|
||||
|
||||
placed = Public.draw_noisy_ore_patch(surface, realp, choice, real_amount, radius_squared, density)
|
||||
|
||||
if placed then
|
||||
choices[choice] = Math.max(0, choices[choice] - Common.ore_real_to_abstract(placed))
|
||||
if placed > 0 and not destination.dynamic_data.ore_types_spawned[choice] then
|
||||
destination.dynamic_data.ore_types_spawned[choice] = true
|
||||
end
|
||||
ret = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- script.raise_event(CustomEvents.enum['update_crew_progress_gui'], {})
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.draw_noisy_ore_patch(surface, position, name, budget, radius_squared, density, forced, flat)
|
||||
flat = flat or false
|
||||
budget = budget or 999999999
|
||||
forced = forced or false
|
||||
local amountplaced = 0
|
||||
local radius = Math.sqrt(radius_squared)
|
||||
|
||||
position = {x = Math.ceil(position.x) - 0.5, y = Math.ceil(position.y) - 0.5}
|
||||
|
||||
if not position then return 0 end
|
||||
if not name then return 0 end
|
||||
if not surface then return 0 end
|
||||
if not radius then return 0 end
|
||||
if not density then return 0 end
|
||||
local mixed_ore_raffle = {
|
||||
'iron-ore', 'iron-ore', 'iron-ore', 'copper-ore', 'copper-ore', 'coal', 'stone'
|
||||
}
|
||||
local seed = surface.map_gen_settings.seed
|
||||
|
||||
local function try_draw_at_relative_position(x, y, strength)
|
||||
local absx = x + position.x
|
||||
local absy = y + position.y
|
||||
local absp = {x = absx, y = absy}
|
||||
|
||||
local amount_to_place_here = Math.min(density * strength, budget - amountplaced)
|
||||
|
||||
if amount_to_place_here >= Common.minimum_ore_placed_per_tile then
|
||||
|
||||
if name == 'mixed' then
|
||||
local noise = simplex_noise(x * 0.005, y * 0.005, seed) + simplex_noise(x * 0.01, y * 0.01, seed) * 0.3 + simplex_noise(x * 0.05, y * 0.05, seed) * 0.2
|
||||
local i = (Math.floor(noise * 100) % #mixed_ore_raffle) + 1
|
||||
name = mixed_ore_raffle[i]
|
||||
end
|
||||
local entity = {name = name, position = absp, amount = amount_to_place_here}
|
||||
-- local area = {{absx - 0.05, absy - 0.05}, {absx + 0.05, absy + 0.05}}
|
||||
local area2 = {{absx - 0.1, absy - 0.1}, {absx + 0.1, absy + 0.1}}
|
||||
local area3 = {{absx - 2, absy - 2}, {absx + 2, absy + 2}}
|
||||
local preexisting_ores = surface.find_entities_filtered{area = area2, type = 'resource'}
|
||||
|
||||
local added
|
||||
if #preexisting_ores >= 1 then
|
||||
local addedbool = false
|
||||
for _, ore in pairs(preexisting_ores) do
|
||||
if ore.name == name then
|
||||
ore.amount = ore.amount + amount_to_place_here
|
||||
amountplaced = amountplaced + amount_to_place_here
|
||||
addedbool = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not addedbool then
|
||||
added = surface.create_entity(entity)
|
||||
end
|
||||
else
|
||||
local tile = surface.get_tile(absp)
|
||||
local silos = surface.find_entities_filtered{area=area3, name='rocket-silo'}
|
||||
if #silos == 0 and (not (tile and tile.name and Utils.contains(CoreData.tiles_that_conflict_with_resource_layer_extended, tile.name))) then
|
||||
if forced then
|
||||
surface.destroy_decoratives{area = area2}
|
||||
for _, tree in pairs(surface.find_entities_filtered{area=area2, type='tree'}) do
|
||||
tree.destroy()
|
||||
end
|
||||
added = surface.create_entity(entity)
|
||||
else
|
||||
local pos2 = surface.find_non_colliding_position(name, absp, 10, 1, true)
|
||||
pos2 = pos2 or absp
|
||||
entity = {name = name, position = pos2, amount = amount_to_place_here}
|
||||
surface.destroy_decoratives{area = area2}
|
||||
if pos2 and surface.can_place_entity(entity) then
|
||||
added = surface.create_entity(entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if added and added.valid then
|
||||
amountplaced = amountplaced + amount_to_place_here
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, p in ipairs(Math.points_in_m20t20_squared_sorted_by_distance_to_origin) do
|
||||
local x, y = p[1], p[2]
|
||||
local distance_to_center = Math.sqrt(x^2 + y^2)
|
||||
local noise
|
||||
if flat then
|
||||
noise = 0.99 * simplex_noise((position.x + x) * 1/3, (position.y + y) * 1/3, seed) * simplex_noise((position.x + x) * 1/9, (position.y + y) * 1/9, seed+100)
|
||||
else --put noise on the unit circle
|
||||
if distance_to_center > 0 then
|
||||
noise = 0.99 * simplex_noise((position.x + x/distance_to_center) * 1/3, (position.y + y/distance_to_center) * 1/3, seed) * simplex_noise((position.x + x/distance_to_center) * 1/9, (position.y + y/distance_to_center) * 1/9, seed+100)
|
||||
else
|
||||
noise = 0.99 * simplex_noise((position.x) * 1/3, (position.y) * 1/3, seed) * simplex_noise((position.x) * 1/9, (position.y) * 1/9, seed+100)
|
||||
end
|
||||
end
|
||||
local radius_noisy = radius * (1 + noise)
|
||||
if distance_to_center < radius_noisy then
|
||||
local strength
|
||||
if flat then
|
||||
-- if noise > -0.5 then strength = 1 else strength = 0 end
|
||||
-- its hard to make it both noncircular and flat in per-tile count
|
||||
strength = 1
|
||||
else
|
||||
strength = (3/2) * (1 - (distance_to_center/radius_noisy)^2)
|
||||
end
|
||||
try_draw_at_relative_position(x, y, strength)
|
||||
end
|
||||
if amountplaced >= budget then break end
|
||||
end
|
||||
|
||||
return amountplaced
|
||||
end
|
||||
|
||||
|
||||
return Public
|
744
maps/pirates/overworld.lua
Normal file
744
maps/pirates/overworld.lua
Normal file
@ -0,0 +1,744 @@
|
||||
|
||||
local Public = {}
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
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 Server = require 'utils.server'
|
||||
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
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 Sea = require 'maps.pirates.surfaces.sea.sea'
|
||||
local Crew = require 'maps.pirates.crew'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
local Classes = require 'maps.pirates.roles.classes'
|
||||
-- local Quest = require 'maps.pirates.quest'
|
||||
-- local Parrot = require 'maps.pirates.parrot'
|
||||
-- local Hold = require 'maps.pirates.surfaces.hold'
|
||||
-- local Cabin = require 'maps.pirates.surfaces.cabin'
|
||||
local Shop = require 'maps.pirates.shop.shop'
|
||||
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 infront_positions = {}
|
||||
for x = -6, -3 do
|
||||
for y = - 3, 3 do
|
||||
infront_positions[#infront_positions + 1] = {x = x, y = y}
|
||||
end
|
||||
end
|
||||
local interior_positions = {}
|
||||
for x = 1, 14 do
|
||||
for y = - 3, 3 do
|
||||
interior_positions[#interior_positions + 1] = {x = x, y = y}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.generate_destination_type_and_subtype(overworld_position)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local macro_p = {x = overworld_position.x/40, y = overworld_position.y/24}
|
||||
local macro_x = macro_p.x
|
||||
local macro_y = macro_p.y
|
||||
|
||||
local type, subtype
|
||||
|
||||
local island_subtype_raffle = {'none', 'none', Surfaces.Island.enum.STANDARD, Surfaces.Island.enum.STANDARD_VARIANT, Surfaces.Island.enum.RED_DESERT, Surfaces.Island.enum.HORSESHOE}
|
||||
|
||||
if macro_x >= 6 then island_subtype_raffle[#island_subtype_raffle + 1] = Surfaces.Island.enum.WALKWAYS end
|
||||
if macro_x >= 6 then island_subtype_raffle[#island_subtype_raffle + 1] = 'none' end
|
||||
-- if macro_x >= 13 and macro_y == 1 then
|
||||
-- island_subtype_raffle[#island_subtype_raffle + 1] = Surfaces.Island.enum.MAZE
|
||||
-- island_subtype_raffle[#island_subtype_raffle + 1] = Surfaces.Island.enum.MAZE
|
||||
-- end
|
||||
if macro_x >= 21 then island_subtype_raffle[#island_subtype_raffle + 1] = Surfaces.Island.enum.SWAMP end
|
||||
if macro_x >= 21 then island_subtype_raffle[#island_subtype_raffle + 1] = 'none' end
|
||||
|
||||
--avoid duplicate subtype twice in a row in the same lane
|
||||
for _, d in pairs(memory.destinations) do
|
||||
if d.subtype and d.overworld_position.x == macro_p.x - 40 and d.overworld_position.y == macro_p.y then
|
||||
local new_island_subtype_raffle = Utils.ordered_table_with_values_removed(island_subtype_raffle, d.subtype)
|
||||
-- if _DEBUG and #new_island_subtype_raffle ~= #island_subtype_raffle then
|
||||
-- game.print('Removed ' .. d.subtype .. ' from raffle at ' .. p.x .. ',' .. p.y)
|
||||
-- end
|
||||
island_subtype_raffle = new_island_subtype_raffle
|
||||
end
|
||||
end
|
||||
-- some other raffle removals for smoothness:
|
||||
if macro_x == 4 then
|
||||
island_subtype_raffle = Utils.ordered_table_with_values_removed(island_subtype_raffle, Surfaces.Island.enum.STANDARD)
|
||||
end
|
||||
if macro_x == 18 then
|
||||
island_subtype_raffle = Utils.ordered_table_with_values_removed(island_subtype_raffle, 'none') --flying-robot-frame cost is here, and we just make sure there's an island to see it
|
||||
end
|
||||
if macro_x == 19 then
|
||||
island_subtype_raffle = Utils.ordered_table_with_values_removed(island_subtype_raffle, Surfaces.Island.enum.SWAMP)
|
||||
end
|
||||
|
||||
if macro_x == 0 then
|
||||
if macro_y == 0 then
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.FIRST
|
||||
elseif macro_y == -1 then
|
||||
type = Surfaces.enum.DOCK
|
||||
else
|
||||
type = nil
|
||||
end
|
||||
elseif macro_x == 1 then
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.HORSESHOE --map where you break rocks
|
||||
elseif macro_x == 2 then
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.STANDARD_VARIANT --aesthetically different to first map
|
||||
elseif (macro_x > 25 and (macro_x - 22) % 20 == 0) then --we want this to overwrite dock, so putting it here.
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.RADIOACTIVE
|
||||
elseif (macro_x > 25 and (macro_x - 22) % 20 == 18) then --we want this to overwrite dock, so putting it here. should be even so rocket launch is forced
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.MAZE
|
||||
elseif macro_x == 23 then --overwrite dock. rocket launch cost
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.WALKWAYS
|
||||
elseif macro_y == -1 and (((macro_x % 4) == 3 and macro_x ~= 15) or macro_x == 14) then --avoid x=15 because radioactive is there
|
||||
type = Surfaces.enum.DOCK
|
||||
elseif macro_x == 3 then
|
||||
type = nil
|
||||
elseif macro_x == 5 then --biter boats appear. large island works well so players run off
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.STANDARD
|
||||
elseif macro_x == 6 then
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.MAZE
|
||||
elseif macro_x == 8 then --game length decrease, pending more content
|
||||
type = nil
|
||||
-- elseif macro_x == 9 then --just before krakens
|
||||
-- type = Surfaces.enum.ISLAND
|
||||
-- subtype = Surfaces.Island.enum.RED_DESERT
|
||||
elseif macro_x == 10 then --krakens appear
|
||||
type = nil
|
||||
-- elseif macro_x == 11 then
|
||||
-- if macro_y == -1 then
|
||||
-- type = Surfaces.enum.ISLAND
|
||||
-- subtype = Surfaces.Island.enum.MAZE
|
||||
-- else
|
||||
-- type = nil
|
||||
-- end
|
||||
elseif macro_x == 11 then --just after krakens, but dock is here too, so there's a choice
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.SWAMP
|
||||
elseif macro_x == 16 then
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.RADIOACTIVE
|
||||
--electric engines needed at 20
|
||||
-- elseif macro_x == 17 then --game length decrease, pending more content
|
||||
-- type = nil
|
||||
elseif macro_x == 20 then --game length decrease, pending more content
|
||||
type = nil
|
||||
elseif macro_x == 21 then --rocket launch cost
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.SWAMP
|
||||
elseif macro_x == 22 then --game length decrease, pending more content. also kinda fun to have to steer in realtime due to double space
|
||||
type = nil
|
||||
elseif macro_x == 24 then --rocket launch cost
|
||||
type = Surfaces.enum.ISLAND
|
||||
subtype = Surfaces.Island.enum.MAZE
|
||||
elseif macro_x == 25 then
|
||||
type = nil --finish line
|
||||
else
|
||||
type = Surfaces.enum.ISLAND
|
||||
|
||||
if #island_subtype_raffle > 0 then
|
||||
subtype = island_subtype_raffle[Math.random(#island_subtype_raffle)]
|
||||
else
|
||||
subtype = 'none'
|
||||
end
|
||||
|
||||
if subtype == 'none' then
|
||||
type = nil
|
||||
subtype = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--== DEBUG override to test islands:
|
||||
|
||||
-- if _DEBUG and type == Surfaces.enum.ISLAND then
|
||||
-- subtype = Surfaces.Island.enum.MAZE
|
||||
-- -- subtype = nil
|
||||
-- -- type = Surfaces.enum.DOCK
|
||||
-- end
|
||||
|
||||
-- warning: the first map is unique in that it isn't all loaded by the time you arrive, which can cause issues. For example, structures might get placed after ore, thereby deleting the ore underneath them.
|
||||
|
||||
-- if _DEBUG and ((macro_p.x > 0 and macro_p.x < 25)) and type ~= Surfaces.enum.DOCK then
|
||||
-- type = nil
|
||||
-- subtype = nil
|
||||
-- end
|
||||
|
||||
return {type = type, subtype = subtype}
|
||||
end
|
||||
|
||||
|
||||
function Public.generate_overworld_destination(p)
|
||||
-- be careful when calling any Balance functions that depend on overworldx — they will be evaluated when the island is chosen, not on arrival
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local macro_p = {x = p.x/40, y = p.y/24}
|
||||
|
||||
local type_data = Public.generate_destination_type_and_subtype(p)
|
||||
local type = type_data.type
|
||||
local subtype = type_data.subtype
|
||||
|
||||
if type == Surfaces.enum.ISLAND then
|
||||
|
||||
local scope = Surfaces[Surfaces.enum.ISLAND][subtype]
|
||||
|
||||
local static_params = Utils.deepcopy(scope.Data.static_params_default)
|
||||
local base_cost_to_undock
|
||||
|
||||
local normal_costitems = {'electronic-circuit', 'advanced-circuit'}
|
||||
|
||||
-- These need to scale up slightly slower than the static fuel depletion rate, so you're increasingly incentivised to leave:
|
||||
local base_cost_1 = {
|
||||
['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*120),
|
||||
}
|
||||
local base_cost_2 = {
|
||||
['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*180),
|
||||
['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*18),
|
||||
-- the below got this response from a new player: "This feels... underwhelming."
|
||||
-- ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*120),
|
||||
-- ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*18),
|
||||
}
|
||||
local base_cost_2b = {
|
||||
['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*180),
|
||||
['flying-robot-frame'] = 3,
|
||||
}
|
||||
local base_cost_3 = {
|
||||
['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*140),
|
||||
['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*18),
|
||||
['launch_rocket'] = true,
|
||||
}
|
||||
local base_cost_4 = {
|
||||
['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*100),
|
||||
['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*18),
|
||||
['flying-robot-frame'] = Math.ceil(((macro_p.x-18)^(2/3))*10),
|
||||
['launch_rocket'] = true,
|
||||
}
|
||||
local base_cost_5 = {
|
||||
['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*100),
|
||||
['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*18),
|
||||
['flying-robot-frame'] = Math.ceil(((macro_p.x-18)^(2/3))*10),
|
||||
-- ['electronic-circuit'] = Math.ceil(((macro_p.x-2)^(2/3))*100),
|
||||
-- ['advanced-circuit'] = Math.ceil(((macro_p.x-14)^(2/3))*18),
|
||||
-- ['flying-robot-frame'] = Math.ceil(((macro_p.x-18)^(2/3))*10),
|
||||
}
|
||||
-- if macro_p.x == 0 then
|
||||
-- if _DEBUG then
|
||||
-- base_cost_to_undock = {
|
||||
-- ['electronic-circuit'] = 5,
|
||||
-- ['engine-unit'] = 5,
|
||||
-- ['advanced-circuit'] = 5,
|
||||
-- ['flying-robot-frame'] = 5,
|
||||
-- }
|
||||
-- end
|
||||
-- base_cost_to_undock = nil
|
||||
-- elseif macro_p.x <= 6 then
|
||||
if macro_p.x <= 6 then
|
||||
-- base_cost_to_undock = {['electronic-circuit'] = 5}
|
||||
base_cost_to_undock = nil
|
||||
elseif macro_p.x <= 9 then
|
||||
base_cost_to_undock = base_cost_1
|
||||
elseif macro_p.x <= 15 then
|
||||
if macro_p.x % 3 > 0 then
|
||||
base_cost_to_undock = base_cost_1
|
||||
else
|
||||
base_cost_to_undock = nil
|
||||
end
|
||||
elseif macro_p.x == 18 then --a super small amount of flying-robot-frame on a relatively early level so that they see they need lubricant
|
||||
base_cost_to_undock = base_cost_2b
|
||||
elseif macro_p.x <= 20 then
|
||||
if macro_p.x % 3 > 0 then
|
||||
base_cost_to_undock = base_cost_2
|
||||
else
|
||||
base_cost_to_undock = nil
|
||||
end
|
||||
-- after this point, mandatory
|
||||
elseif macro_p.x <= 23 then
|
||||
base_cost_to_undock = base_cost_3
|
||||
elseif macro_p.x <= 24 then
|
||||
base_cost_to_undock = base_cost_4
|
||||
else
|
||||
base_cost_to_undock = Utils.deepcopy(base_cost_5)
|
||||
local delete = normal_costitems[Math.random(#normal_costitems)]
|
||||
base_cost_to_undock[delete] = nil
|
||||
if macro_p.x < 50 then
|
||||
if macro_p.x % 2 == 0 then
|
||||
base_cost_to_undock['launch_rocket'] = true
|
||||
end
|
||||
else --now we're just trying to kill you
|
||||
base_cost_to_undock['launch_rocket'] = true
|
||||
end
|
||||
end
|
||||
-- override:
|
||||
if subtype == Surfaces.Island.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
|
||||
}
|
||||
end
|
||||
|
||||
-- -- debug override:
|
||||
-- if _DEBUG then
|
||||
-- base_cost_to_undock = {
|
||||
-- ['electronic-circuit'] = 200,
|
||||
-- ['launch_rocket'] = true,
|
||||
-- }
|
||||
-- end
|
||||
|
||||
static_params.base_cost_to_undock = base_cost_to_undock -- Multiplication by Balance.cost_to_leave_multiplier() happens later, in destination_on_collide.
|
||||
|
||||
--scheduled raft raids moved to destination_on_arrival
|
||||
|
||||
local ores_multiplier = Balance.island_richness_avg_multiplier()
|
||||
if macro_p.x == 0 then ores_multiplier = 0.9 end
|
||||
|
||||
local base_ores = scope.Data.base_ores()
|
||||
|
||||
local rngs = {}
|
||||
local rngsum = 0
|
||||
local rngcount = 0
|
||||
for k, _ in pairs(base_ores) do
|
||||
if k ~= 'coal' then
|
||||
local rng = 2*Math.random()
|
||||
-- local rng = 1 + ((2*Math.random() - 1)^3) --lower variances
|
||||
rngs[k] = rng
|
||||
rngsum = rngsum + rng
|
||||
rngcount = rngcount + 1
|
||||
end
|
||||
end
|
||||
|
||||
local abstract_ore_amounts = {}
|
||||
for k, v in pairs(base_ores) do
|
||||
local rng = 1
|
||||
if not (k == 'coal' or macro_p.x == 0) then
|
||||
rng = rngs[k] / (rngsum/rngcount) --average of 1
|
||||
end
|
||||
abstract_ore_amounts[k] = ores_multiplier * v * rng
|
||||
end
|
||||
static_params.abstract_ore_amounts = abstract_ore_amounts
|
||||
|
||||
static_params.radius_squared_modifier = (2 + 2 * Math.random())
|
||||
|
||||
if macro_p.x == 0 then static_params.radius_squared_modifier = 1.75 end
|
||||
|
||||
static_params.discord_emoji = scope.Data.discord_emoji
|
||||
|
||||
local rng = 0.5 + 1 * Math.random()
|
||||
static_params.starting_treasure_maps = Math.ceil((static_params.base_starting_treasure_maps or 0) * rng)
|
||||
static_params.starting_wood = Math.ceil(static_params.base_starting_wood or 1000)
|
||||
static_params.starting_rock_material = Math.ceil(static_params.base_starting_rock_material or 300) * Balance.island_richness_avg_multiplier()
|
||||
|
||||
rng = 0.5 + 1 * Math.random()
|
||||
static_params.starting_treasure = Math.ceil((static_params.base_starting_treasure or 1000) * Balance.island_richness_avg_multiplier() * rng)
|
||||
|
||||
static_params.name = scope.Data.display_names[Math.random(#scope.Data.display_names)]
|
||||
|
||||
local dest = Surfaces.initialise_destination{
|
||||
static_params = static_params,
|
||||
type = type,
|
||||
subtype = subtype,
|
||||
overworld_position = p,
|
||||
}
|
||||
|
||||
Crowsnest.draw_destination(dest)
|
||||
|
||||
elseif type == Surfaces.enum.DOCK then
|
||||
|
||||
local boat_for_sale_type
|
||||
-- if macro_p.x == 3 then
|
||||
-- boat_for_sale_type = Boats.enum.CUTTER
|
||||
-- elseif macro_p.x == 7 or macro_p.x == 0 then
|
||||
-- boat_for_sale_type = Boats.enum.SLOOP_WITH_HOLD
|
||||
-- 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()
|
||||
-- one day it's worth making this system more readable
|
||||
|
||||
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
|
||||
|
||||
static_params.name = Dock.Data.display_names[Math.random(#Dock.Data.display_names)]
|
||||
|
||||
local dest = Surfaces.initialise_destination{
|
||||
static_params = static_params,
|
||||
type = type,
|
||||
subtype = subtype,
|
||||
overworld_position = {x = p.x, y = -36},
|
||||
-- overworld_position = {x = p.x, y = 36},
|
||||
}
|
||||
|
||||
Crowsnest.draw_destination(dest)
|
||||
|
||||
-- renderings e.g. for docks
|
||||
|
||||
local surface = Crowsnest.get_crowsnest_surface()
|
||||
local x = Crowsnest.platformrightmostedge + dest.overworld_position.x
|
||||
local y = dest.overworld_position.y
|
||||
if dest.static_params.upgrade_for_sale then
|
||||
local display_form = Upgrades.crowsnest_display_form[dest.static_params.upgrade_for_sale]
|
||||
|
||||
if not dest.dynamic_data.crowsnest_renderings then
|
||||
dest.dynamic_data.crowsnest_renderings = {}
|
||||
end
|
||||
|
||||
dest.dynamic_data.crowsnest_renderings.base_text_rendering = rendering.draw_text{
|
||||
text = display_form .. ':',
|
||||
surface = surface,
|
||||
target = {x = x + 5.5, y = y + 2.5},
|
||||
color = CoreData.colors.renderingtext_green,
|
||||
scale = 7,
|
||||
font = 'default-game',
|
||||
alignment = 'right',
|
||||
visible = false,
|
||||
}
|
||||
|
||||
local i = 1
|
||||
for price_name, price_count in pairs(Shop.Captains.main_shop_data_1[dest.static_params.upgrade_for_sale].base_cost) do
|
||||
local sprite
|
||||
if price_name == 'fuel' then
|
||||
sprite = 'item/coal'
|
||||
else
|
||||
sprite = 'item/coin'
|
||||
end
|
||||
dest.dynamic_data.crowsnest_renderings[price_name] = {
|
||||
text_rendering = rendering.draw_text{
|
||||
text = Utils.bignumber_abbrevform2(price_count),
|
||||
surface = surface,
|
||||
target = {x = x + 6, y = y + 8.3 - i * 3.5},
|
||||
color = CoreData.colors.renderingtext_green,
|
||||
scale = 5.2,
|
||||
font = 'default-game',
|
||||
alignment = 'left',
|
||||
visible = false,
|
||||
},
|
||||
sprite_rendering = rendering.draw_sprite{
|
||||
sprite = sprite,
|
||||
surface = surface,
|
||||
target = {x = x + 14.1, y = y + 10.8 - i * 3.5},
|
||||
x_scale = 4.5,
|
||||
y_scale = 4.5,
|
||||
visible = false,
|
||||
}
|
||||
}
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--== krakens ==--
|
||||
|
||||
local kraken_count = 0
|
||||
local position_candidates
|
||||
if type == nil then
|
||||
kraken_count = Balance.krakens_per_free_slot(p.x)
|
||||
position_candidates = interior_positions
|
||||
elseif type ~= Surfaces.enum.DOCK then
|
||||
kraken_count = Balance.krakens_per_slot()
|
||||
position_candidates = infront_positions
|
||||
end
|
||||
|
||||
-- override:
|
||||
if macro_p.x < 10 then
|
||||
kraken_count = 0
|
||||
elseif macro_p.x == 10 then
|
||||
kraken_count = 1
|
||||
end
|
||||
|
||||
-- if _DEBUG then
|
||||
-- kraken_count = 1
|
||||
-- end
|
||||
|
||||
if position_candidates then
|
||||
local positions_placed = {}
|
||||
local whilesafety = 0
|
||||
while whilesafety < 10 and (#positions_placed < Math.min(kraken_count, 10)) do
|
||||
local p_chosen, p_kraken
|
||||
local whilesafety2 = 0
|
||||
while whilesafety2 < 50 and ((not p_kraken) or Utils.contains(positions_placed, p_chosen)) do
|
||||
p_chosen = position_candidates[Math.random(#position_candidates)]
|
||||
p_kraken = Utils.psum{p_chosen, p}
|
||||
whilesafety2 = whilesafety2 + 1
|
||||
end
|
||||
Crowsnest.draw_kraken(p_kraken)
|
||||
positions_placed[#positions_placed + 1] = p_kraken
|
||||
memory.overworld_krakens[#memory.overworld_krakens + 1] = p_kraken
|
||||
whilesafety = whilesafety + 1
|
||||
end
|
||||
-- game.print(#positions_placed .. ' krakens placed for' .. macro_p.x .. ', ' .. macro_p.y)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.ensure_lane_generated_up_to(lane_yvalue, x)
|
||||
-- make sure lane_yvalue=0 is painted first
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local highest_x = memory['greatest_overworldx_generated_for_' .. lane_yvalue] or -40
|
||||
|
||||
local whilesafety = 0
|
||||
while whilesafety < 10 and highest_x < x do
|
||||
whilesafety = whilesafety + 1
|
||||
|
||||
highest_x = highest_x + 32 + 7 + 1 -- should be at least maximum island size plus crowsnest platform size plus 1
|
||||
|
||||
if lane_yvalue == 0 then
|
||||
Crowsnest.paint_water_between_overworld_positions(highest_x + 32 + 7 + 1, highest_x + 32 + 7 + 1 + 40)
|
||||
-- a little hack that we're updating this here rather than Crowsnest, due to the dependency on Shop to avoid a loop... almost finished 1.0, so too late to figure out how to restructure things for now!
|
||||
for _, dest in pairs(memory.destinations) do
|
||||
if dest.static_params.upgrade_for_sale and dest.dynamic_data.crowsnest_renderings then
|
||||
if rendering.is_valid(dest.dynamic_data.crowsnest_renderings.base_text_rendering) then
|
||||
rendering.set_text(dest.dynamic_data.crowsnest_renderings.base_text_rendering, Upgrades.crowsnest_display_form[dest.static_params.upgrade_for_sale] .. ':')
|
||||
end
|
||||
for rendering_name, r in pairs(dest.dynamic_data.crowsnest_renderings) do
|
||||
if type(r) == 'table' and r.text_rendering and rendering.is_valid(r.text_rendering) then
|
||||
rendering.set_text(r.text_rendering, Utils.bignumber_abbrevform2(Shop.Captains.main_shop_data_1[dest.static_params.upgrade_for_sale].base_cost[rendering_name]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Crowsnest.update_destination_renderings()
|
||||
end
|
||||
Public.generate_overworld_destination{x = highest_x, y = lane_yvalue}
|
||||
end
|
||||
|
||||
memory['greatest_overworldx_generated_for_' .. lane_yvalue] = highest_x
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.is_position_free_to_move_to(p)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local ret = true
|
||||
|
||||
for _, destination_data in pairs(memory.destinations) do
|
||||
if p.x >= destination_data.overworld_position.x + 1 and p.x <= destination_data.overworld_position.x + destination_data.iconized_map_width + Crowsnest.platformwidth - 1 and p.y >= destination_data.overworld_position.y - destination_data.iconized_map_width/2 - Crowsnest.platformheight/2 + 1 and p.y <= destination_data.overworld_position.y + destination_data.iconized_map_width/2 + Crowsnest.platformheight/2 - 1 then
|
||||
ret = false
|
||||
break
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.check_for_kraken_collisions()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local krakens = memory.overworld_krakens
|
||||
|
||||
for i, k in ipairs(krakens) do
|
||||
|
||||
local relativex = Crowsnest.platformrightmostedge + k.x - memory.overworldx
|
||||
local relativey = k.y - memory.overworldy
|
||||
|
||||
if (relativex <= 3.5 and relativex >= -3.5 and relativey >= -4 and relativey <= 4) then
|
||||
Kraken.try_spawn_kraken()
|
||||
memory.overworld_krakens = Utils.ordered_table_with_index_removed(krakens, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.check_for_destination_collisions()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
-- if memory.overworldx > CoreData.victory_x - 10 then return end
|
||||
-- to avoid crashing into the finish line...
|
||||
|
||||
for _, destination_data in pairs(memory.destinations) do
|
||||
|
||||
local relativex = Crowsnest.platformrightmostedge + destination_data.overworld_position.x - memory.overworldx
|
||||
local relativey = destination_data.overworld_position.y - memory.overworldy
|
||||
|
||||
if (relativex == 4 and relativey + destination_data.iconized_map_height/2 >= -3.5 and relativey - destination_data.iconized_map_height/2 <= 3.5) then
|
||||
--or (relativey - destination_data.iconized_map.height/2 == 5 and (relativex >= -3.5 or relativex <= 4.5)) or (relativey + destination_data.iconized_map.height/2 == -4 and (relativex >= -3.5 or relativex <= 4.5))
|
||||
|
||||
Surfaces.clean_up(Common.current_destination())
|
||||
|
||||
Surfaces.create_surface(destination_data)
|
||||
|
||||
local index = destination_data.destination_index
|
||||
memory.loadingticks = 0
|
||||
memory.mapbeingloadeddestination_index = index
|
||||
memory.currentdestination_index = index
|
||||
memory.boat.state = Boats.enum_state.ATSEA_LOADING_MAP
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_progress_gui'], {})
|
||||
|
||||
local destination = Common.current_destination()
|
||||
Surfaces.destination_on_collide(destination)
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.try_overworld_move_v2(vector) --islands stay, crowsnest moves
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if memory.game_lost or (memory.victory_pause_until_tick and game.tick < memory.victory_pause_until_tick) then return end
|
||||
|
||||
if memory.victory_continue_message then
|
||||
memory.victory_continue_message = false
|
||||
local message = 'The run now continues on \'Freeplay\'.'
|
||||
Common.notify_force(memory.force, message, CoreData.colors.notify_victory)
|
||||
end
|
||||
|
||||
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()
|
||||
|
||||
if not Public.is_position_free_to_move_to{x = memory.overworldx + vector.x, y = memory.overworldy+ vector.y} then
|
||||
if _DEBUG then log(string.format('can\'t move by ' .. vector.x .. ', ' .. vector.y)) end
|
||||
return false
|
||||
else
|
||||
|
||||
Crowsnest.move_crowsnest(vector.x, vector.y)
|
||||
|
||||
if vector.x > 0 then
|
||||
|
||||
-- crew bonus resources per x:
|
||||
local crew = Common.crew_get_crew_members()
|
||||
for _, player in pairs(crew) do
|
||||
if Common.validate_player_and_character(player) then
|
||||
local player_index = player.index
|
||||
if memory.classes_table and memory.classes_table[player_index] and memory.classes_table[player_index] == Classes.enum.MERCHANT then
|
||||
Common.flying_text_small(player.surface, player.position, '[color=0.97,0.9,0.2]+[/color]')
|
||||
Common.give_items_to_crew{{name = 'coin', count = 40 * vector.x}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- other freebies:
|
||||
for i=1,vector.x do
|
||||
Common.give_items_to_crew(Balance.periodic_free_resources_per_x())
|
||||
Balance.apply_crew_buffs_per_x(memory.force)
|
||||
end
|
||||
|
||||
-- add some evo: (this will get reset upon arriving at a destination anyway, so this is just relevant for sea monsters and the like:)
|
||||
local extra_evo = Balance.base_evolution_leagues(memory.overworldx) - Balance.base_evolution_leagues(memory.overworldx - vector.x)
|
||||
Common.increment_evo(extra_evo)
|
||||
end
|
||||
|
||||
if memory.overworldx >= CoreData.victory_x then
|
||||
Crew.try_win()
|
||||
end
|
||||
|
||||
if memory.overworldx % 40 == 0 then
|
||||
local modal_captain = nil
|
||||
local modal_captain_time = 0
|
||||
for name, time in pairs(memory.captain_accrued_time_data) do
|
||||
if time > modal_captain_time then
|
||||
modal_captain_time = time
|
||||
modal_captain = name
|
||||
end
|
||||
end
|
||||
Highscore.write_score(memory.secs_id, memory.name, modal_captain, memory.completion_time or 0, memory.overworldx, CoreData.version_float, memory.difficulty, memory.max_players_recorded or 0)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
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
|
||||
local upgrade_to_overwrite_with
|
||||
|
||||
if not memory.dock_overwrite_variable then memory.dock_overwrite_variable = 1 end
|
||||
|
||||
local possible_overwrites = {}
|
||||
if (not memory.merchant_ships_unlocked) then
|
||||
possible_overwrites[#possible_overwrites + 1] = Upgrades.enum.UNLOCK_MERCHANTS
|
||||
end
|
||||
if (not memory.rockets_for_sale) then
|
||||
possible_overwrites[#possible_overwrites + 1] = Upgrades.enum.ROCKETS_FOR_SALE
|
||||
end
|
||||
|
||||
if #possible_overwrites > 0 then
|
||||
if memory.dock_overwrite_variable > #possible_overwrites then memory.dock_overwrite_variable = 1 end
|
||||
upgrade_to_overwrite_with = possible_overwrites[memory.dock_overwrite_variable]
|
||||
|
||||
-- bump the variable up, but only if the list hasn't reduced in length. use a second variable to track this:
|
||||
if memory.dock_overwrite_variable_2 and memory.dock_overwrite_variable_2 == #possible_overwrites then
|
||||
memory.dock_overwrite_variable = memory.dock_overwrite_variable + 1
|
||||
end
|
||||
memory.dock_overwrite_variable_2 = #possible_overwrites
|
||||
end
|
||||
|
||||
if upgrade_to_overwrite_with then
|
||||
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 = upgrade_to_overwrite_with
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
303
maps/pirates/parrot.lua
Normal file
303
maps/pirates/parrot.lua
Normal file
@ -0,0 +1,303 @@
|
||||
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
-- local Token = require 'utils.token'
|
||||
-- local CoreData = require 'maps.pirates.coredata'
|
||||
-- local Task = require 'utils.task'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
IDLE_FLY = 'idle_fly',
|
||||
FLY = 'fly',
|
||||
TIP_FLYING_1 = 'tip_flying_1',
|
||||
TIP_FLYING_2 = 'tip_flying_2',
|
||||
TIP_LANDED_1 = 'tip_landed_1',
|
||||
TIP_LANDED_2 = 'tip_landed_2',
|
||||
TIP_SQUAWK = 'tip_squawk',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
-- local parrot_tip_interval = 15*60
|
||||
|
||||
Public.framecounts = {
|
||||
idle_fly = 5,
|
||||
fly = 8,
|
||||
fly_right = 8,
|
||||
squawk = 6,
|
||||
freak = 2,
|
||||
walk = 8,
|
||||
chill = 1,
|
||||
}
|
||||
|
||||
-- local parrot_tips = {
|
||||
-- "Why not buy the map designer a coffee! ko-fi.com/thesixthroc!",
|
||||
-- "Why not buy the map designer a coffee! ko-fi.com/thesixthroc!",
|
||||
-- "Make suggestions at getcomfy.eu/discord!",
|
||||
-- "To launch a second run, you need a fifth of the server's pirates to endorse it!",
|
||||
-- "Resources granted to the ship appear in the captain's cabin!",
|
||||
-- "On each island after the first, the ship generates ore!",
|
||||
-- "Charge the silo to launch a rocket!",
|
||||
-- "Launching rockets makes fuel and doubloon!",
|
||||
-- "Charging silos makes pollution and evo!",
|
||||
-- "The number of non-afk crewmembers affects pollution, evo and maximum stay time!",
|
||||
-- "Once a silo has launched a rocket, biters will ignore it!",
|
||||
-- "Charging a silo drains power from everything else on the network...",
|
||||
-- "You can steer the boat from the crow's nest by placing 100 rail signals in one of the blue boxes!",
|
||||
-- "When you visit a dock, the shop is updated with special trades!",
|
||||
-- "Labs produce more research the further you've travelled!",
|
||||
-- "On radioactive islands, biters don\'t care if you emit pollution! They only care how long you stay...",
|
||||
-- "If X marks the spot - use inserters to dig!",
|
||||
-- }
|
||||
|
||||
function Public.parrot_0()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, 'We can wait here for as long as we like.')
|
||||
end
|
||||
-- function Public.parrot_80()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
-- Common.parrot_speak(memory.force, 'Let\'s build out the ship?')
|
||||
-- end
|
||||
function Public.parrot_boats_warning()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, '200 leagues? I think we\'re being chased...')
|
||||
end
|
||||
function Public.parrot_kraken_warning()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, '400 leagues coming up? What are those pink things I spy...')
|
||||
end
|
||||
function Public.parrot_radioactive_tip_1()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, 'We\'ll need uranium-235 to push away from this island...')
|
||||
end
|
||||
function Public.parrot_radioactive_tip_2()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, 'The biters don\'t care if we pollute here, but they evolve fast...')
|
||||
end
|
||||
function Public.parrot_maze_tip_1()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, 'Something seems wrong with our minimap.')
|
||||
end
|
||||
function Public.parrot_800_tip()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, 'The resources needed to leave will get a bit harder now...')
|
||||
end
|
||||
function Public.parrot_overstay_tip()
|
||||
local memory = Memory.get_crew_memory()
|
||||
Common.parrot_speak(memory.force, 'We\'ve been here quite a while! Check the evo...')
|
||||
end
|
||||
|
||||
-- function Public.parrot_say_tip()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
-- local crew_force = memory.force
|
||||
|
||||
-- local tip = parrot_tips[Math.random(#parrot_tips)]
|
||||
-- Common.parrot_speak(crew_force, tip)
|
||||
-- end
|
||||
|
||||
|
||||
|
||||
-- function Public.parrot_tick()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
-- if not (memory.boat and memory.boat.surface_name) then return end
|
||||
-- local surface = game.surfaces[memory.boat.surface_name]
|
||||
-- if not surface and surface.valid then return end
|
||||
-- local destination = Common.current_destination()
|
||||
|
||||
-- if destination.dynamic_data and destination.dynamic_data.timer and destination.dynamic_data.timer == Math.ceil(Balance.expected_time_on_island()) and (not destination.dynamic_data.parrot_gave_overstay_tip) then
|
||||
-- destination.dynamic_data.parrot_gave_overstay_tip = true
|
||||
|
||||
-- local spawners = surface.find_entities_filtered({type = 'unit-spawner', force = memory.enemy_force_name})
|
||||
-- local spawnerscount = #spawners or 0
|
||||
-- if spawnerscount > 0 then --check biter bases actually exist
|
||||
-- Public.parrot_overstay_tip()
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- local boat = memory.boat
|
||||
-- local parrot = boat.parrot
|
||||
-- local frame = parrot.frame
|
||||
-- local render = parrot.render
|
||||
-- local render_name = parrot.render_name
|
||||
-- local state = parrot.state
|
||||
-- local state_counter = parrot.state_counter or parrot_tip_interval*60/5
|
||||
-- local resting_position_relative_to_boat = parrot.resting_position_relative_to_boat
|
||||
-- local position_relative_to_boat = parrot.position_relative_to_boat
|
||||
-- local sprite_extra_offset = boat.parrot.sprite_extra_offset
|
||||
-- local text_extra_offset = boat.parrot.text_extra_offset
|
||||
-- local real_position = Utils.psum{position_relative_to_boat, boat.position}
|
||||
|
||||
-- if state == enum.IDLE_FLY then
|
||||
-- local ate_fish
|
||||
|
||||
-- if boat.state and boat.state == 'landed' and state_counter >= parrot_tip_interval*60/5 then
|
||||
-- local nearby_characters = surface.find_entities_filtered{position = real_position, radius = 4, name = 'character'}
|
||||
-- local nearby_characters_count = #nearby_characters
|
||||
-- if nearby_characters_count > 0 then
|
||||
-- local j = 1
|
||||
-- while j <= nearby_characters_count do
|
||||
-- if nearby_characters[j] and nearby_characters[j].valid and nearby_characters[j].player and Common.validate_player(nearby_characters[j].player) then
|
||||
-- local player = nearby_characters[j].player
|
||||
-- local inv = player.get_inventory(defines.inventory.character_main)
|
||||
-- if inv and inv.get_item_count('raw-fish') >= 2 then
|
||||
-- Common.give(player, {{name = 'raw-fish', count = -2, color = CoreData.colors.fish}})
|
||||
-- ate_fish = true
|
||||
-- break
|
||||
-- end
|
||||
-- end
|
||||
-- j = j + 1
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- state_counter = state_counter + 1
|
||||
|
||||
-- if ate_fish then
|
||||
-- Common.parrot_speak(memory.force, 'Tasty...')
|
||||
|
||||
-- local p1 = {x = boat.position.x - 15 - Math.random(35), y = boat.position.y - 8 + Math.random(15)}
|
||||
-- local p2 = surface.find_non_colliding_position('stone-furnace', p1, 6, 0.5)
|
||||
|
||||
-- parrot.spot_to_fly_from = position_relative_to_boat
|
||||
-- local real_fly_to = p2 or p1
|
||||
-- parrot.spot_to_fly_to = {x = real_fly_to.x - boat.position.x, y = real_fly_to.y - boat.position.y}
|
||||
-- parrot.fly_distance = Math.distance(parrot.spot_to_fly_from, parrot.spot_to_fly_to)
|
||||
-- state = enum.TIP_FLYING_1
|
||||
-- state_counter = 0
|
||||
-- else
|
||||
-- if game.tick % 10 == 0 then
|
||||
-- frame = frame + 1
|
||||
-- end
|
||||
|
||||
-- if boat.speed and boat.speed > 0 then
|
||||
-- state = enum.FLY
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- elseif state == enum.TIP_FLYING_1 then
|
||||
|
||||
-- if boat.speed and boat.speed > 0 then
|
||||
-- state_counter = 0
|
||||
-- state = enum.IDLE_FLY
|
||||
-- position_relative_to_boat = resting_position_relative_to_boat
|
||||
-- else
|
||||
-- if game.tick % 10 == 0 then
|
||||
-- frame = frame + 1
|
||||
-- end
|
||||
|
||||
-- if state_counter < parrot.fly_distance then
|
||||
-- position_relative_to_boat = Utils.interpolate(parrot.spot_to_fly_from, parrot.spot_to_fly_to, state_counter/parrot.fly_distance)
|
||||
-- state_counter = state_counter + 0.5
|
||||
-- else
|
||||
-- state_counter = 0
|
||||
-- state = enum.TIP_LANDED_1
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- elseif state == enum.TIP_LANDED_1 then
|
||||
|
||||
-- if boat.speed and boat.speed > 0 then
|
||||
-- state_counter = 0
|
||||
-- state = enum.IDLE_FLY
|
||||
-- position_relative_to_boat = resting_position_relative_to_boat
|
||||
-- else
|
||||
-- if state_counter < 20 then
|
||||
-- state_counter = state_counter + 1
|
||||
-- else
|
||||
-- state_counter = 0
|
||||
-- state = enum.TIP_SQUAWK
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- elseif state == enum.TIP_SQUAWK then
|
||||
|
||||
-- if boat.speed and boat.speed > 0 then
|
||||
-- state_counter = 0
|
||||
-- state = enum.IDLE_FLY
|
||||
-- position_relative_to_boat = resting_position_relative_to_boat
|
||||
-- else
|
||||
-- if state_counter == 0 then
|
||||
-- Public.parrot_say_tip()
|
||||
-- end
|
||||
|
||||
-- if state_counter < 18 then
|
||||
-- if game.tick % 15 == 0 then
|
||||
-- frame = frame + 1
|
||||
-- end
|
||||
-- state_counter = state_counter + 1
|
||||
-- else
|
||||
-- state_counter = 0
|
||||
-- state = enum.TIP_LANDED_2
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- elseif state == enum.TIP_LANDED_2 then
|
||||
|
||||
-- if boat.speed and boat.speed > 0 then
|
||||
-- state_counter = 0
|
||||
-- state = enum.IDLE_FLY
|
||||
-- position_relative_to_boat = resting_position_relative_to_boat
|
||||
-- else
|
||||
-- if state_counter < 20 then
|
||||
-- state_counter = state_counter + 1
|
||||
-- else
|
||||
-- state_counter = 0
|
||||
-- state = enum.TIP_FLYING_2
|
||||
-- local hold = parrot.spot_to_fly_to
|
||||
-- parrot.spot_to_fly_to = parrot.spot_to_fly_from
|
||||
-- parrot.spot_to_fly_from = hold
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- elseif state == enum.TIP_FLYING_2 then
|
||||
|
||||
-- if boat.speed and boat.speed > 0 then
|
||||
-- state_counter = 0
|
||||
-- state = enum.IDLE_FLY
|
||||
-- position_relative_to_boat = resting_position_relative_to_boat
|
||||
-- else
|
||||
-- if game.tick % 10 == 0 then
|
||||
-- frame = frame + 1
|
||||
-- end
|
||||
|
||||
-- if state_counter < parrot.fly_distance then
|
||||
-- position_relative_to_boat = Utils.interpolate(parrot.spot_to_fly_from, parrot.spot_to_fly_to, state_counter/parrot.fly_distance)
|
||||
-- state_counter = state_counter + 0.5
|
||||
-- else
|
||||
-- state_counter = 0
|
||||
-- state = enum.IDLE_FLY
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- elseif state == enum.FLY then
|
||||
|
||||
-- if game.tick % 10 == 0 then
|
||||
-- frame = frame + 1
|
||||
-- end
|
||||
|
||||
-- if (not boat.speed) or (boat.speed == 0) then state = enum.IDLE_FLY end
|
||||
-- end
|
||||
|
||||
-- local sprite_name = state
|
||||
-- if state == enum.TIP_FLYING_1 then sprite_name = 'fly' end
|
||||
-- if state == enum.TIP_FLYING_2 then sprite_name = 'fly_right' end
|
||||
-- if state == enum.TIP_LANDED_1 or state == enum.TIP_LANDED_2 then sprite_name = 'chill' end
|
||||
-- if state == enum.TIP_SQUAWK then sprite_name = 'squawk' end
|
||||
|
||||
-- if frame > Public.framecounts[sprite_name] then frame = 1 end
|
||||
-- parrot.state = state
|
||||
-- parrot.frame = frame
|
||||
-- parrot.state_counter = state_counter
|
||||
-- parrot.position_relative_to_boat = position_relative_to_boat
|
||||
|
||||
-- rendering.set_sprite(render, "file/parrot/parrot_" .. sprite_name .. "_" .. frame .. ".png")
|
||||
-- rendering.set_target(render, rendering.get_target(render).entity, Utils.psum{sprite_extra_offset, position_relative_to_boat})
|
||||
-- rendering.set_visible(render, true)
|
||||
-- rendering.set_target(render_name, rendering.get_target(render_name).entity, Utils.psum{text_extra_offset, position_relative_to_boat})
|
||||
-- rendering.set_visible(render_name, true)
|
||||
-- end
|
||||
|
||||
return Public
|
1275
maps/pirates/player_colors.lua
Normal file
1275
maps/pirates/player_colors.lua
Normal file
File diff suppressed because one or more lines are too long
597
maps/pirates/progression.lua
Normal file
597
maps/pirates/progression.lua
Normal file
@ -0,0 +1,597 @@
|
||||
|
||||
local Public = {}
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
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 CustomEvents = require 'maps.pirates.custom_events'
|
||||
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
|
||||
local Server = require 'utils.server'
|
||||
local Dock = require 'maps.pirates.surfaces.dock'
|
||||
-- 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'
|
||||
-- local Parrot = require 'maps.pirates.parrot'
|
||||
-- local Quest = require 'maps.pirates.quest'
|
||||
|
||||
local Shop = require 'maps.pirates.shop.shop'
|
||||
local Overworld = require 'maps.pirates.overworld'
|
||||
local Hold = require 'maps.pirates.surfaces.hold'
|
||||
local Cabin = require 'maps.pirates.surfaces.cabin'
|
||||
local Upgrades = require 'maps.pirates.boat_upgrades'
|
||||
local Task = require 'utils.task'
|
||||
local Token = require 'utils.token'
|
||||
local ShopDock = require 'maps.pirates.shop.dock'
|
||||
|
||||
|
||||
|
||||
function Public.fuel_depletion_rate()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local state = memory.boat.state
|
||||
|
||||
if state == Boats.enum_state.ATSEA_SAILING or state == Boats.enum_state.APPROACHING then
|
||||
return Balance.fuel_depletion_rate_sailing()
|
||||
elseif state == Boats.enum_state.LEAVING_DOCK then
|
||||
return Balance.fuel_depletion_rate_sailing() * 2
|
||||
elseif state == Boats.enum_state.RETREATING then
|
||||
return Balance.fuel_depletion_rate_sailing() / 4
|
||||
elseif state == Boats.enum_state.LANDED then
|
||||
return Balance.fuel_depletion_rate_static()
|
||||
elseif state == Boats.enum_state.DOCKED then
|
||||
return -0.1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.set_off_from_starting_dock()
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.game_lost then return end
|
||||
|
||||
memory.crewstatus = Crew.enum.LEAVING_INITIAL_DOCK
|
||||
memory.boat.state = Boats.enum_state.LEAVING_DOCK
|
||||
|
||||
Boats.place_boat(memory.boat, CoreData.moving_boat_floor, false, false)
|
||||
|
||||
Common.current_destination().type = Surfaces.enum.LOBBY
|
||||
|
||||
memory.mapbeingloadeddestination_index = 1 -- whatever the index of the first island is
|
||||
memory.loadingticks = 0
|
||||
|
||||
local surface = game.surfaces[CoreData.lobby_surface_name]
|
||||
local p = Utils.psum{memory.boat.position, Boats.get_scope(memory.boat).Data.crewname_rendering_position}
|
||||
memory.boat.rendering_crewname_text = rendering.draw_text{
|
||||
text = memory.name,
|
||||
-- render_layer = '125', --does nothing
|
||||
surface = surface,
|
||||
target = p,
|
||||
color = CoreData.colors.renderingtext_yellow,
|
||||
scale = 8,
|
||||
font = 'default-game',
|
||||
alignment = 'left'
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.go_from_starting_dock_to_first_destination()
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
local crew_members = Crew.choose_crew_members()
|
||||
local crew_members_count = #memory.crewplayerindices
|
||||
|
||||
if crew_members_count > 0 then
|
||||
memory.crewstatus = Crew.enum.ADVENTURING
|
||||
|
||||
local message = '[' .. memory.name .. '] Crew members: '
|
||||
local b = false
|
||||
for _, index in pairs(memory.crewplayerindices) do
|
||||
if game.players[index] and game.players[index].name then
|
||||
if b == true then
|
||||
message = message .. ', '
|
||||
else b = true end
|
||||
message = message .. game.players[index].name
|
||||
end
|
||||
end
|
||||
message = message .. '.'
|
||||
Server.to_discord_embed_raw(CoreData.comfy_emojis.pogkot .. message)
|
||||
|
||||
Roles.assign_captain_based_on_priorities()
|
||||
|
||||
for _, player in pairs(crew_members) do
|
||||
Crew.player_abandon_endorsements(player)
|
||||
for item, amount in pairs(Balance.starting_items_player) do
|
||||
player.insert({name = item, count = amount})
|
||||
end
|
||||
end
|
||||
|
||||
boat.stored_resources = {}
|
||||
|
||||
Shop.Captains.initialise_captains_shop()
|
||||
|
||||
Hold.create_hold_surface(1)
|
||||
Cabin.create_cabin_surface()
|
||||
|
||||
local items = Balance.starting_items_crew_upstairs()
|
||||
-- Boats.deck_place_random_obstacle_boxes(boat, 6, items, 0)
|
||||
|
||||
-- Let's try just adding the items to nearby boxes
|
||||
local scope = Boats.get_scope(boat)
|
||||
local surface = game.surfaces[boat.surface_name]
|
||||
local boxes = surface.find_entities_filtered{
|
||||
name = 'wooden-chest',
|
||||
area = {
|
||||
{x = boat.position.x - scope.Data.width/2, y = boat.position.y - scope.Data.height/2},
|
||||
{x = boat.position.x + scope.Data.width/2, y = boat.position.y + scope.Data.height/2}
|
||||
},
|
||||
}
|
||||
boxes = Math.shuffle(boxes)
|
||||
for i = 1, #items do
|
||||
if boxes[i] then
|
||||
local inventory = boxes[i].get_inventory(defines.inventory.chest)
|
||||
for name, count in pairs(items[i]) do
|
||||
inventory.insert{name = name, count = count}
|
||||
end
|
||||
else
|
||||
game.print('fail at ' .. boxes[i].position.x .. ' ' .. boxes[i].position.y)
|
||||
end
|
||||
end
|
||||
|
||||
Public.progress_to_destination(1) --index of first destination
|
||||
|
||||
-- local scope = Boats.get_scope(boat)
|
||||
-- local boatwidth, boatheight = scope.Data.width, scope.Data.height
|
||||
-- Common.surface_place_random_obstacle_boxes(game.surfaces[boat.surface_name], {x = boat.position.x - boatwidth*0.575, y = boat.position.y}, boatwidth*0.85, boatheight*0.8, 'oil-refinery', {[1] = 3, [2] = 3, [3] = 0, [4] = 0}, items)
|
||||
-- go:
|
||||
-- Public.progress_to_destination(1) --index of first destination
|
||||
|
||||
boat.EEI_stage = 1
|
||||
Boats.update_EEIs(boat)
|
||||
|
||||
-- if Common.difficulty() == 1 then
|
||||
-- Boats.upgrade_chests(boat, 'iron-chest')
|
||||
-- Hold.upgrade_chests(1, 'iron-chest')
|
||||
-- Crowsnest.upgrade_chests('iron-chest')
|
||||
-- elseif Common.difficulty() > 1 then
|
||||
-- Boats.upgrade_chests(boat, 'steel-chest')
|
||||
-- Hold.upgrade_chests(1, 'steel-chest')
|
||||
-- Crowsnest.upgrade_chests('steel-chest')
|
||||
-- end
|
||||
|
||||
memory.age = 0
|
||||
memory.real_age = 0
|
||||
|
||||
else
|
||||
Boats.destroy_boat(boat)
|
||||
Crew.disband_crew()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local place_dock_jetty_and_boats = Token.register(
|
||||
function(data)
|
||||
Memory.set_working_id(data.crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.game_lost then return end
|
||||
Surfaces.Dock.place_dock_jetty_and_boats()
|
||||
|
||||
local destination = Common.current_destination()
|
||||
ShopDock.create_dock_markets(game.surfaces[destination.surface_name], Surfaces.Dock.Data.markets_position)
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
|
||||
function Public.progress_to_destination(destination_index)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.game_lost then return end
|
||||
|
||||
local boat = memory.boat
|
||||
|
||||
local oldsurface = game.surfaces[boat.surface_name]
|
||||
local old_type = Surfaces.SurfacesCommon.decode_surface_name(oldsurface.name).type
|
||||
|
||||
local destination_data = memory.destinations[destination_index]
|
||||
local static_params = destination_data.static_params
|
||||
local type = destination_data.type
|
||||
local subtype = destination_data.subtype
|
||||
local newsurface_name = Surfaces.SurfacesCommon.encode_surface_name(memory.id, destination_index, type, subtype)
|
||||
local newsurface = game.surfaces[newsurface_name]
|
||||
|
||||
local initial_boatspeed, starting_boatposition
|
||||
|
||||
if type == Surfaces.enum.ISLAND then --moved from overworld generation, so that it updates properly
|
||||
local covered1_requirement = Balance.covered1_entry_price()
|
||||
destination_data.dynamic_data.covered1_requirement = covered1_requirement
|
||||
end
|
||||
|
||||
if type == Surfaces.enum.DOCK then
|
||||
local BoatData = Boats.get_scope(boat).Data
|
||||
starting_boatposition = Utils.snap_coordinates_for_rails({x = Dock.Data.playerboat_starting_xcoord, y = Dock.Data.player_boat_top + BoatData.height/2})
|
||||
-- starting_boatposition = {x = -destination_data.static_params.width/2 + BoatData.width + 10, y = Dock.Data.player_boat_top - BoatData.height/2}
|
||||
Common.current_destination().dynamic_data.time_remaining = 180
|
||||
|
||||
-- memory.mainshop_availability_bools.sell_iron = true
|
||||
memory.mainshop_availability_bools.buy_iron = true
|
||||
memory.mainshop_availability_bools.buy_copper = true
|
||||
-- memory.mainshop_availability_bools.buy_fast_loader = true
|
||||
-- memory.mainshop_availability_bools.sell_copper = true
|
||||
|
||||
memory.mainshop_availability_bools.repair_cannons = true
|
||||
|
||||
local boat_for_sale_type = Common.current_destination().static_params.boat_for_sale_type
|
||||
if boat_for_sale_type then
|
||||
if boat_for_sale_type == Boats.enum.CUTTER then
|
||||
memory.mainshop_availability_bools.new_boat_cutter = true
|
||||
elseif boat_for_sale_type == Boats.enum.CUTTER_WITH_HOLD then
|
||||
memory.mainshop_availability_bools.new_boat_cutter_with_hold = true
|
||||
elseif boat_for_sale_type == Boats.enum.SLOOP_WITH_HOLD then
|
||||
memory.mainshop_availability_bools.new_boat_sloop_with_hold = true
|
||||
end
|
||||
end
|
||||
|
||||
local upgrade_for_sale = Common.current_destination().static_params.upgrade_for_sale
|
||||
if upgrade_for_sale then
|
||||
for _, u in pairs(Upgrades.List) do
|
||||
if upgrade_for_sale == u then
|
||||
memory.mainshop_availability_bools[u] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_fuel_gui'], {})
|
||||
|
||||
-- Delay.add(Delay.enum.PLACE_DOCK_JETTY_AND_BOATS)
|
||||
Task.set_timeout_in_ticks(2, place_dock_jetty_and_boats, {crew_id = memory.id})
|
||||
else
|
||||
starting_boatposition = {x = static_params.boat_starting_xposition, y = static_params.boat_starting_yposition or 0}
|
||||
end
|
||||
|
||||
-- if oldsurface.name == CoreData.lobby_surface_name then
|
||||
-- initial_boatspeed = 3
|
||||
-- else
|
||||
-- initial_boatspeed = 1.5
|
||||
-- end
|
||||
initial_boatspeed = 1.4
|
||||
|
||||
boat.speed = initial_boatspeed
|
||||
boat.state = destination_data.init_boat_state
|
||||
boat.dockedposition = nil
|
||||
|
||||
memory.enemyboats = {}
|
||||
|
||||
local old_water = 'deepwater'
|
||||
if old_type == Surfaces.enum.LOBBY or old_type == Surfaces.enum.DOCK then old_water = 'water' end
|
||||
|
||||
Boats.teleport_boat(boat, newsurface_name, starting_boatposition, CoreData.moving_boat_floor, old_water)
|
||||
|
||||
|
||||
if old_type == Surfaces.enum.LOBBY then
|
||||
Crowsnest.draw_extra_bits()
|
||||
end
|
||||
Crowsnest.paint_around_destination(destination_index, CoreData.overworld_presence_tile)
|
||||
|
||||
|
||||
if memory.loadingticks then memory.loadingticks = -120 end
|
||||
|
||||
if old_type == Surfaces.enum.SEA then
|
||||
game.delete_surface(oldsurface)
|
||||
end
|
||||
|
||||
memory.destinationsvisited_indices[#memory.destinationsvisited_indices + 1] = destination_index
|
||||
|
||||
memory.currentdestination_index = destination_index --already done when we collide with it typically
|
||||
local destination = Common.current_destination()
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_progress_gui'], {})
|
||||
|
||||
destination.dynamic_data.timer = 0
|
||||
destination.dynamic_data.timeratlandingtime = nil
|
||||
|
||||
memory.extra_time_at_sea = 0
|
||||
|
||||
if old_type == Surfaces.enum.SEA or old_type == Surfaces.enum.CHANNEL or old_type == Surfaces.enum.DOCK then
|
||||
-- move over anyone who was left behind, such as dead and spectating players
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if type == Surfaces.enum.ISLAND and player.controller_type == defines.controllers.spectator then
|
||||
if player.surface == oldsurface then --avoid moving players in hold etc
|
||||
-- put them at a nice viewing position:
|
||||
player.teleport({x = memory.spawnpoint.x + 120, y = memory.spawnpoint.y}, newsurface)
|
||||
end
|
||||
elseif player.surface == oldsurface then
|
||||
player.teleport(memory.spawnpoint, newsurface)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Surfaces.destination_on_arrival(Common.current_destination())
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.check_for_end_of_boat_movement(boat)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
local collided = Boats.collision_infront(boat)
|
||||
|
||||
local approaching_island = boat.state == Boats.enum_state.APPROACHING and destination.type == Surfaces.enum.ISLAND
|
||||
local retreating_island = boat.state == Boats.enum_state.RETREATING and destination.type == Surfaces.enum.ISLAND
|
||||
|
||||
local approaching_dock = destination.type == Surfaces.enum.DOCK and boat.state == Boats.enum_state.APPROACHING
|
||||
local leaving_dock = destination.type == Surfaces.enum.DOCK and boat.state == Boats.enum_state.LEAVING_DOCK
|
||||
|
||||
--=== Collision
|
||||
if approaching_island and collided then
|
||||
boat.state = Boats.enum_state.LANDED
|
||||
boat.speed = 0
|
||||
boat.dockedposition = boat.position
|
||||
|
||||
|
||||
game.surfaces[boat.surface_name].play_sound{path = "utility/axe_fighting"}
|
||||
game.surfaces[boat.surface_name].play_sound{path = "utility/axe_fighting"}
|
||||
end
|
||||
|
||||
--=== Enemy
|
||||
if boat.force_name == memory.enemy_force_name then
|
||||
|
||||
if approaching_island then
|
||||
|
||||
if collided then
|
||||
boat.landing_time = destination.dynamic_data.timer
|
||||
|
||||
Boats.place_landingtrack(boat, CoreData.enemy_landing_tile)
|
||||
|
||||
return true
|
||||
|
||||
-- elseif boat.spawner and boat.spawner.valid and boat.spawner.destructible then
|
||||
-- -- This code was somehow making the spawners destructible but still able to be shot at.
|
||||
-- local boat2 = Utils.deepcopy(boat)
|
||||
-- boat2.position = {x = boat.position.x + 6, y = boat.position.y}
|
||||
-- if Boats.collision_infront(boat2) then
|
||||
-- boat.spawner.destructible = false
|
||||
-- end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--=== Friendly
|
||||
elseif boat.force_name == memory.force_name then
|
||||
|
||||
if approaching_island and collided then
|
||||
|
||||
Surfaces.destination_on_crewboat_hits_shore(destination)
|
||||
return true
|
||||
|
||||
elseif retreating_island and boat.position.x < ((boat.dockedposition.x or 999) - Boats.get_scope(boat).Data.width - 2 * Boats.get_scope(boat).Data.rightmost_gate_position - 8) then
|
||||
|
||||
Public.go_from_currentdestination_to_sea()
|
||||
return true
|
||||
|
||||
|
||||
elseif approaching_dock and boat.position.x + Boats.get_scope(boat).Data.rightmost_gate_position >= Dock.Data.rightmostgate_stopping_xposition then
|
||||
|
||||
boat.state = Boats.enum_state.DOCKED
|
||||
boat.speed = 0
|
||||
boat.dockedposition = boat.position
|
||||
|
||||
destination.dynamic_data.timeratlandingtime = destination.dynamic_data.timer
|
||||
|
||||
Boats.place_boat(boat, CoreData.static_boat_floor, false, false)
|
||||
return true
|
||||
|
||||
|
||||
elseif leaving_dock and boat.position.x >= game.surfaces[boat.surface_name].map_gen_settings.width/2 - 60 then
|
||||
|
||||
memory.mainshop_availability_bools.new_boat_cutter = false
|
||||
memory.mainshop_availability_bools.new_boat_cutter_with_hold = false
|
||||
memory.mainshop_availability_bools.new_boat_sloop_with_hold = false
|
||||
-- memory.mainshop_availability_bools.sell_iron = false
|
||||
memory.mainshop_availability_bools.buy_iron = false
|
||||
memory.mainshop_availability_bools.buy_copper = false
|
||||
-- memory.mainshop_availability_bools.buy_fast_loader = false
|
||||
-- memory.mainshop_availability_bools.sell_copper = false
|
||||
memory.mainshop_availability_bools.repair_cannons = false
|
||||
|
||||
memory.mainshop_availability_bools.extra_hold = false
|
||||
memory.mainshop_availability_bools.upgrade_power = false
|
||||
memory.mainshop_availability_bools.unlock_merchants = false
|
||||
memory.mainshop_availability_bools.rockets_for_sale = false
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_fuel_gui'], {})
|
||||
|
||||
Public.go_from_currentdestination_to_sea()
|
||||
|
||||
return true
|
||||
|
||||
|
||||
--=== Fallthrough right-hand side
|
||||
elseif destination.type == Surfaces.enum.ISLAND and boat.position.x >= game.surfaces[boat.surface_name].map_gen_settings.width/2 - 10 then
|
||||
Public.go_from_currentdestination_to_sea()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.try_retreat_from_island(player, manual) -- Assumes the cost can be paid
|
||||
local memory = Memory.get_crew_memory()
|
||||
if memory.game_lost then return end
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if Common.query_can_pay_cost_to_leave() then
|
||||
if destination.dynamic_data.timeratlandingtime and destination.dynamic_data.timer < destination.dynamic_data.timeratlandingtime + 10 then
|
||||
if player and Common.validate_player(player) then
|
||||
Common.notify_player_error(player, 'Undock error: Can\'t undock in the first 10 seconds.')
|
||||
end
|
||||
else
|
||||
local cost = destination.static_params.base_cost_to_undock
|
||||
|
||||
if cost then
|
||||
local adjusted_cost = Common.time_adjusted_departure_cost(cost)
|
||||
|
||||
Common.spend_stored_resources(adjusted_cost)
|
||||
end
|
||||
Public.retreat_from_island(manual)
|
||||
end
|
||||
else
|
||||
if player and Common.validate_player(player) then
|
||||
Common.notify_player_error(player.force, 'Undock error: Not enough resources stored in the captain\'s cabin.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.retreat_from_island(manual)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
if boat.state and boat.state == Boats.enum_state.RETREATING then return end
|
||||
|
||||
boat.state = Boats.enum_state.RETREATING
|
||||
boat.speed = 1.25
|
||||
|
||||
Boats.place_boat(boat, CoreData.moving_boat_floor, false, false)
|
||||
|
||||
local force = memory.force
|
||||
if not (force and force.valid) then return end
|
||||
if manual then
|
||||
Common.notify_force(force,'[font=heading-1]Ship undocked[/font] by captain.')
|
||||
else
|
||||
Common.notify_force(force,'[font=heading-1]Ship auto-undocked[/font]. Return to ship.')
|
||||
end
|
||||
|
||||
Surfaces.destination_on_departure(Common.current_destination())
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.undock_from_dock(manual)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
local destination = Common.current_destination()
|
||||
|
||||
boat.state = Boats.enum_state.LEAVING_DOCK
|
||||
destination.dynamic_data.time_remaining = -1
|
||||
|
||||
Boats.place_boat(boat, CoreData.moving_boat_floor, false, false)
|
||||
|
||||
memory.mainshop_availability_bools.new_boat_cutter = false
|
||||
memory.mainshop_availability_bools.new_boat_cutter_with_hold = false
|
||||
memory.mainshop_availability_bools.new_boat_sloop_with_hold = false
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_fuel_gui'], {})
|
||||
|
||||
Crew.summon_crew()
|
||||
|
||||
local force = memory.force
|
||||
if not (force and force.valid) then return end
|
||||
if manual then
|
||||
Common.notify_force(force,'[font=heading-1]Ship undocked[/font].')
|
||||
else
|
||||
Common.notify_force(force,'[font=heading-1]Ship auto-undocked[/font].')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.go_from_currentdestination_to_sea()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
if memory.game_lost then return end
|
||||
|
||||
local oldsurface = game.surfaces[destination.surface_name]
|
||||
|
||||
Sea.ensure_sea_surface()
|
||||
local seaname = memory.sea_name
|
||||
|
||||
local boat = memory.boat
|
||||
|
||||
local new_boatposition = Utils.snap_coordinates_for_rails({x = Boats.get_scope(memory.boat).Data.width / 2, y = 0})
|
||||
|
||||
Boats.teleport_boat(boat, seaname, new_boatposition, CoreData.static_boat_floor, 'water')
|
||||
|
||||
if memory.overworldx == 0 and memory.boat then
|
||||
|
||||
local difficulty_name = CoreData.get_difficulty_name_from_value(Common.difficulty())
|
||||
if difficulty_name == CoreData.difficulty_options[#CoreData.difficulty_options].text then
|
||||
Boats.upgrade_chests(boat, 'steel-chest')
|
||||
Hold.upgrade_chests(1, 'steel-chest')
|
||||
Crowsnest.upgrade_chests('steel-chest')
|
||||
|
||||
Common.parrot_speak(memory.force, 'Steel chests for steel players! Squawk!')
|
||||
elseif difficulty_name ~= CoreData.difficulty_options[1].text then
|
||||
Boats.upgrade_chests(boat, 'iron-chest')
|
||||
Hold.upgrade_chests(1, 'iron-chest')
|
||||
Crowsnest.upgrade_chests('iron-chest')
|
||||
|
||||
Common.parrot_speak(memory.force, 'Iron chests for iron players! Squawk!')
|
||||
end
|
||||
end
|
||||
|
||||
memory.boat.state = Boats.enum_state.ATSEA_SAILING
|
||||
memory.boat.speed = 0
|
||||
memory.boat.position = new_boatposition
|
||||
memory.boat.surface_name = seaname
|
||||
|
||||
memory.enemy_force.reset_evolution()
|
||||
|
||||
--@FIX: This doesn't change the evo during sea travel, which is relevant now that krakens are in the game:
|
||||
local base_evo = Balance.base_evolution_leagues(memory.overworldx)
|
||||
Common.set_evo(base_evo)
|
||||
memory.kraken_evo = 0
|
||||
|
||||
memory.loadingticks = nil
|
||||
memory.mapbeingloadeddestination_index = nil
|
||||
|
||||
local d = destination.iconized_map_width + Crowsnest.platformwidth
|
||||
|
||||
Crowsnest.paint_around_destination(destination.destination_index, 'deepwater')
|
||||
|
||||
Overworld.try_overworld_move_v2{x = d, y = 0}
|
||||
|
||||
|
||||
local players_marooned_count = 0
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if (player.surface == oldsurface and player.character and player.character.valid) then
|
||||
players_marooned_count = players_marooned_count + 1
|
||||
end
|
||||
end
|
||||
if players_marooned_count == 0 then
|
||||
Surfaces.clean_up(destination)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
401
maps/pirates/quest.lua
Normal file
401
maps/pirates/quest.lua
Normal file
@ -0,0 +1,401 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Loot = require 'maps.pirates.loot'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
|
||||
local Public = {}
|
||||
|
||||
local enum = {
|
||||
TIME = 'Time',
|
||||
FIND = 'Find',
|
||||
NODAMAGE = 'No_Damage',
|
||||
RESOURCEFLOW = 'Resource_Flow',
|
||||
RESOURCECOUNT = 'Resource_Count',
|
||||
WORMS = 'Worms',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
Public.quest_icons = {
|
||||
[enum.TIME] = '[img=utility.time_editor_icon]',
|
||||
[enum.NODAMAGE] = '[item=stone-wall]',
|
||||
[enum.WORMS] = '[entity=small-worm-turret]',
|
||||
[enum.FIND] = '[img=utility.ghost_time_to_live_modifier_icon]',
|
||||
[enum.RESOURCEFLOW] = '',
|
||||
[enum.RESOURCECOUNT] = '',
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- @TODO remake into a loot-style table:
|
||||
|
||||
function Public.quest_reward()
|
||||
local ret
|
||||
local multiplier = Balance.quest_reward_multiplier()
|
||||
local rng = Math.random()
|
||||
|
||||
if rng <= 0.3 then
|
||||
ret = {name = 'iron-plate', count = Math.ceil(2000 * multiplier), display_sprite = '[item=iron-plate]', display_amount = string.format('%.1fk', 2 * multiplier), chat_name = '[item=iron-plate]'}
|
||||
elseif rng <= 0.5 then
|
||||
ret = {name = 'copper-plate', count = Math.ceil(2000 * multiplier), display_sprite = '[item=copper-plate]', display_amount = string.format('%.1fk', 2 * multiplier), chat_name = '[item=copper-plate]'}
|
||||
elseif rng <= 0.7 then
|
||||
ret = {name = 'solid-fuel', count = Math.ceil(450 * multiplier), display_sprite = '[item=solid-fuel]', display_amount = string.format('%.0f', Math.ceil(450 * multiplier)), chat_name = '[item=solid-fuel]'}
|
||||
elseif rng <= 0.9 then
|
||||
ret = {name = 'coin', count = Math.ceil(6000 * (multiplier^(1/2))), display_sprite = '[item=coin]', display_amount = string.format('%.1fk', Math.ceil(6 * (multiplier^(1/2)))), chat_name = 'doubloons'}
|
||||
else
|
||||
ret = {name = 'piercing-rounds-magazine', count = Math.ceil(250 * multiplier), display_sprite = '[item=piercing-rounds-magazine]', display_amount = string.format('%.0f', Math.ceil(250 * multiplier)), chat_name = '[item=piercing-rounds-magazine]'}
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.initialise_random_quest()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
destination.dynamic_data.quest_complete = false
|
||||
|
||||
if destination.destination_index == 2 then return end
|
||||
|
||||
local rng = Math.random(10)
|
||||
if rng == 1 then
|
||||
Public.initialise_nodamage_quest()
|
||||
elseif rng <= 3 then
|
||||
Public.initialise_worms_quest()
|
||||
elseif rng <= 5 then
|
||||
Public.initialise_time_quest()
|
||||
elseif rng <= 7 then
|
||||
Public.initialise_find_quest()
|
||||
elseif rng <= 10 then
|
||||
Public.initialise_resourcecount_quest()
|
||||
-- Public.initialise_resourceflow_quest()
|
||||
end
|
||||
|
||||
-- Public.initialise_time_quest()
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.initialise_time_quest()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
destination.dynamic_data.quest_type = enum.TIME
|
||||
destination.dynamic_data.quest_reward = Public.quest_reward()
|
||||
destination.dynamic_data.quest_progress = Balance.time_quest_seconds()
|
||||
destination.dynamic_data.quest_progressneeded = 9999999
|
||||
|
||||
return true
|
||||
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
|
||||
|
||||
destination.dynamic_data.quest_type = enum.FIND
|
||||
destination.dynamic_data.quest_reward = Public.quest_reward()
|
||||
destination.dynamic_data.quest_progress = 0
|
||||
if #Common.crew_get_crew_members() > 15 then
|
||||
destination.dynamic_data.quest_progressneeded = 2
|
||||
else
|
||||
destination.dynamic_data.quest_progressneeded = 1
|
||||
end
|
||||
return true
|
||||
else
|
||||
log('Find quest not appropriate, rerolling')
|
||||
Public.initialise_random_quest() --@FIXME: mild danger of loop
|
||||
return false
|
||||
end
|
||||
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
|
||||
|
||||
destination.dynamic_data.quest_type = enum.NODAMAGE
|
||||
destination.dynamic_data.quest_reward = Public.quest_reward()
|
||||
destination.dynamic_data.quest_progress = 0
|
||||
destination.dynamic_data.quest_progressneeded = destination.dynamic_data.rocketsilomaxhp
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
|
||||
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()
|
||||
destination.dynamic_data.quest_params = {item = generated_flow_quest.item}
|
||||
|
||||
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
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function Public.initialise_resourcecount_quest()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if not destination and destination.dynamic_data and destination.dynamic_data.rocketsilomaxhp then return end
|
||||
|
||||
destination.dynamic_data.quest_type = enum.RESOURCECOUNT
|
||||
destination.dynamic_data.quest_reward = Public.quest_reward()
|
||||
destination.dynamic_data.quest_progress = 0
|
||||
|
||||
local generated_production_quest = Public.generate_resourcecount_quest()
|
||||
destination.dynamic_data.quest_params = {item = generated_production_quest.item}
|
||||
|
||||
local force = memory.force
|
||||
if force and force.valid then
|
||||
destination.dynamic_data.quest_params.initial_count = force.item_production_statistics.get_flow_count{name = generated_production_quest.item, input = true, precision_index = defines.flow_precision_index.one_thousand_hours, count = true}
|
||||
end
|
||||
|
||||
local progressneeded_before_rounding = generated_production_quest.base_rate * Balance.resource_quest_multiplier() * Common.difficulty()
|
||||
|
||||
destination.dynamic_data.quest_progressneeded = Math.ceil(progressneeded_before_rounding/10)*10
|
||||
|
||||
return true
|
||||
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
|
||||
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
|
||||
local worms = surface.find_entities_filtered{type = 'turret'}
|
||||
|
||||
local count = 0
|
||||
for i = 1, #worms do
|
||||
local w = worms[i]
|
||||
if w.destructible then count = count + 1 end
|
||||
end
|
||||
|
||||
local needed = Math.ceil(
|
||||
1 + 9 * Math.slopefromto(count, 0, 20) + 10 * Math.slopefromto(count, 20, 70)
|
||||
)
|
||||
|
||||
if Common.difficulty() < 1 then needed = Math.max(1, needed - 3) end
|
||||
if Common.difficulty() > 1 then needed = Math.max(1, needed + 2) end
|
||||
|
||||
local difficulty_name = CoreData.get_difficulty_name_from_value(Common.difficulty())
|
||||
if difficulty_name == CoreData.difficulty_options[1].text then
|
||||
needed = Math.max(1, needed - 3)
|
||||
elseif difficulty_name ~= CoreData.difficulty_options[2].text then
|
||||
needed = Math.max(1, needed + 2)
|
||||
end
|
||||
|
||||
if needed >= 5 then
|
||||
destination.dynamic_data.quest_type = enum.WORMS
|
||||
destination.dynamic_data.quest_reward = Public.quest_reward()
|
||||
destination.dynamic_data.quest_progress = 0
|
||||
destination.dynamic_data.quest_progressneeded = needed
|
||||
return true
|
||||
else
|
||||
log('Worms quest not appropriate, rerolling')
|
||||
Public.initialise_random_quest() --@FIXME: mild danger of loop
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.try_resolve_quest()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if destination.dynamic_data.quest_type and destination.dynamic_data.quest_progress and destination.dynamic_data.quest_progressneeded and destination.dynamic_data.quest_progress >= destination.dynamic_data.quest_progressneeded and (not destination.dynamic_data.quest_complete) then
|
||||
|
||||
local force = memory.force
|
||||
if not (force and force.valid) then return end
|
||||
Common.notify_force_light(force,'Granted ' .. destination.dynamic_data.quest_reward.display_amount .. ' ' .. destination.dynamic_data.quest_reward.chat_name)
|
||||
|
||||
local name = destination.dynamic_data.quest_reward.name
|
||||
local count = destination.dynamic_data.quest_reward.count
|
||||
|
||||
-- destination.dynamic_data.quest_type = nil
|
||||
-- destination.dynamic_data.quest_reward = nil
|
||||
-- destination.dynamic_data.quest_progress = nil
|
||||
-- destination.dynamic_data.quest_progressneeded = nil
|
||||
destination.dynamic_data.quest_complete = true
|
||||
|
||||
local boat = memory.boat
|
||||
if not boat then return end
|
||||
local surface_name = boat.surface_name
|
||||
if not surface_name then return end
|
||||
local surface = game.surfaces[surface_name]
|
||||
if not (surface and surface.valid) then return end
|
||||
local chest = boat.output_chest
|
||||
if not chest and chest.valid then return end
|
||||
|
||||
local inventory = chest.get_inventory(defines.inventory.chest)
|
||||
local inserted = inventory.insert{name = name, count = count}
|
||||
|
||||
if inserted < count then
|
||||
local chest2 = boat.backup_output_chest
|
||||
if chest2 and chest2.valid then
|
||||
local inventory2 = chest2.get_inventory(defines.inventory.chest)
|
||||
local inserted2 = inventory2.insert{name = name, count = count - inserted}
|
||||
if (inserted + inserted2) < count then
|
||||
Common.notify_force(force,'Sadly, there wasn\'t space in the cabin for all of your reward.')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- Public.flow_quest_data_raw = {
|
||||
-- {0.2, 0, 1, false, 'submachine-gun', 3 * 12},
|
||||
-- {1, 0, 1, false, 'electronic-circuit', 3 * 120},
|
||||
-- {0.2, 0.1, 1, false, 'big-electric-pole', 1 * 120},
|
||||
-- {0.4, 0.2, 1, false, 'engine-unit', 3 * 6},
|
||||
-- -- {1, 0.5, 1, false, 'advanced-circuit', 1 * 10},
|
||||
-- -- {0.3, 0.8, 1, false, 'electric-engine-unit', 1 * 6},
|
||||
-- }
|
||||
|
||||
-- function Public.flow_quest_data()
|
||||
-- local ret = {}
|
||||
-- local data = Public.flow_quest_data_raw
|
||||
-- for i = 1, #data do
|
||||
-- local datum = data[i]
|
||||
-- ret[#ret + 1] = {
|
||||
-- weight = datum[1],
|
||||
-- game_completion_progress_min = datum[2],
|
||||
-- game_completion_progress_max = datum[3],
|
||||
-- scaling = datum[4],
|
||||
-- item = datum[5],
|
||||
-- base_rate = datum[6],
|
||||
-- }
|
||||
-- end
|
||||
-- return ret
|
||||
-- end
|
||||
|
||||
function Public.generate_flow_quest()
|
||||
local game_completion_progress = Common.game_completion_progress_capped()
|
||||
|
||||
local data = Public.flow_quest_data()
|
||||
local v, w = {}, {}
|
||||
|
||||
for i = 1, #data, 1 do
|
||||
table.insert(v, {item = data[i].item, base_rate = data[i].base_rate})
|
||||
|
||||
local destination = Common.current_destination()
|
||||
if not (destination and destination.subtype and data[i].map_subtype and data[i].map_subtype == destination.subtype) then
|
||||
if data[i].scaling then -- scale down weights away from the midpoint 'peak' (without changing the mean)
|
||||
local midpoint = (data[i].game_completion_progress_max + data[i].game_completion_progress_min) / 2
|
||||
local difference = (data[i].game_completion_progress_max - data[i].game_completion_progress_min)
|
||||
table.insert(w, data[i].weight * Math.max(0, 1 - (Math.abs(game_completion_progress - midpoint) / (difference / 2))))
|
||||
else -- no scaling
|
||||
if data[i].game_completion_progress_min <= game_completion_progress and data[i].game_completion_progress_max >= game_completion_progress then
|
||||
table.insert(w, data[i].weight)
|
||||
else
|
||||
table.insert(w, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Math.raffle(v, w)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Public.resourcecount_quest_data_raw = {
|
||||
{1, 0, 1, false, 'iron-gear-wheel', 2400},
|
||||
-- {1, 0, 1, false, 'electronic-circuit', 1400},
|
||||
{1.2, 0, 1, false, 'transport-belt', 1600},
|
||||
{1, 0, 1, false, 'repair-pack', 350},
|
||||
-- {0.1, 0, 1, false, 'red-wire', 500},
|
||||
{0.5, 0, 1, false, 'empty-barrel', 200},
|
||||
{0.3, 0, 0.2, false, 'underground-belt', 200},
|
||||
{0.3, 0, 0.2, false, 'splitter', 150},
|
||||
{0.4, 0.2, 1, false, 'fast-splitter', 60},
|
||||
{0.4, 0.2, 1, false, 'fast-underground-belt', 75},
|
||||
{0.5, 0.3, 1, false, 'big-electric-pole', 160},
|
||||
{1.2, 0.61, 1, false, 'advanced-circuit', 350},
|
||||
{1, 0, 1, false, 'shotgun-shell', 600},
|
||||
{1.5, 0.9, 1, false, 'processing-unit', 40},
|
||||
-- {0.3, 0.8, 1, false, 'electric-engine-unit', 1 * 6},
|
||||
}
|
||||
|
||||
function Public.resourcecount_quest_data()
|
||||
local ret = {}
|
||||
local data = Public.resourcecount_quest_data_raw
|
||||
for i = 1, #data do
|
||||
local datum = data[i]
|
||||
ret[#ret + 1] = {
|
||||
weight = datum[1],
|
||||
game_completion_progress_min = datum[2],
|
||||
game_completion_progress_max = datum[3],
|
||||
scaling = datum[4],
|
||||
item = datum[5],
|
||||
base_rate = datum[6],
|
||||
}
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function Public.generate_resourcecount_quest()
|
||||
local game_completion_progress = Common.game_completion_progress_capped()
|
||||
|
||||
local data = Public.resourcecount_quest_data()
|
||||
local v, w = {}, {}
|
||||
|
||||
for i = 1, #data, 1 do
|
||||
table.insert(v, {item = data[i].item, base_rate = data[i].base_rate})
|
||||
|
||||
local destination = Common.current_destination()
|
||||
if not (destination and destination.subtype and data[i].map_subtype and data[i].map_subtype == destination.subtype) then
|
||||
if data[i].scaling then -- scale down weights away from the midpoint 'peak' (without changing the mean)
|
||||
local midpoint = (data[i].game_completion_progress_max + data[i].game_completion_progress_min) / 2
|
||||
local difference = (data[i].game_completion_progress_max - data[i].game_completion_progress_min)
|
||||
table.insert(w, data[i].weight * Math.max(0, 1 - (Math.abs(game_completion_progress - midpoint) / (difference / 2))))
|
||||
else -- no scaling
|
||||
if data[i].game_completion_progress_min <= game_completion_progress and data[i].game_completion_progress_max >= game_completion_progress then
|
||||
table.insert(w, data[i].weight)
|
||||
else
|
||||
table.insert(w, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Math.raffle(v, w)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
233
maps/pirates/reference/default_map_settings.lua
Normal file
233
maps/pirates/reference/default_map_settings.lua
Normal file
@ -0,0 +1,233 @@
|
||||
-- data:extend(
|
||||
-- {
|
||||
-- {
|
||||
-- type='map-settings',
|
||||
-- name='map-settings',
|
||||
-- pollution=
|
||||
-- {
|
||||
-- enabled=true,
|
||||
-- -- these are values for 60 ticks (1 simulated second)
|
||||
-- --
|
||||
-- -- amount that is diffused to neighboring chunk
|
||||
-- -- (possibly repeated for other directions as well)
|
||||
-- diffusion_ratio=0.02,
|
||||
-- -- this much PUs must be on the chunk to start diffusing
|
||||
-- min_to_diffuse=15,
|
||||
-- -- constant modifier a percentage of 1 - the pollution eaten by a chunks tiles
|
||||
-- ageing=1,
|
||||
-- -- anything bigger than this is visualised as this value
|
||||
-- expected_max_per_chunk=150,
|
||||
-- -- anything lower than this (but > 0) is visualised as this value
|
||||
-- min_to_show_per_chunk=50,
|
||||
-- min_pollution_to_damage_trees = 60,
|
||||
-- pollution_with_max_forest_damage = 150,
|
||||
-- pollution_per_tree_damage = 50,
|
||||
-- pollution_restored_per_tree_damage = 10,
|
||||
-- max_pollution_to_restore_trees = 20,
|
||||
-- enemy_attack_pollution_consumption_modifier = 1
|
||||
-- },
|
||||
|
||||
-- enemy_evolution=
|
||||
-- {
|
||||
-- enabled=true,
|
||||
-- -- percentual increase in the evolve factor for every second (60 ticks)
|
||||
-- time_factor = 0.000004,
|
||||
-- -- percentual increase in the evolve factor for every destroyed spawner
|
||||
-- destroy_factor = 0.002,
|
||||
-- -- percentual increase in the evolve factor for 1 pollution unit
|
||||
-- pollution_factor = 0.0000009
|
||||
-- },
|
||||
|
||||
-- enemy_expansion=
|
||||
-- {
|
||||
-- enabled = true,
|
||||
-- -- Distance in chunks from the furthest base around.
|
||||
-- -- This prevents expansions from reaching too far into the
|
||||
-- -- player's territory
|
||||
-- max_expansion_distance = 7,
|
||||
|
||||
-- friendly_base_influence_radius = 2,
|
||||
-- enemy_building_influence_radius = 2,
|
||||
|
||||
-- -- A candidate chunk's score is given as follows:
|
||||
-- -- player = 0
|
||||
-- -- for neighbour in all chunks within enemy_building_influence_radius from chunk:
|
||||
-- -- player += number of player buildings on neighbour
|
||||
-- -- * building_coefficient
|
||||
-- -- * neighbouring_chunk_coefficient^distance(chunk, neighbour)
|
||||
-- --
|
||||
-- -- base = 0
|
||||
-- -- for neighbour in all chunk within friendly_base_influence_radius from chunk:
|
||||
-- -- base += num of enemy bases on neighbour
|
||||
-- -- * other_base_coefficient
|
||||
-- -- * neighbouring_base_chunk_coefficient^distance(chunk, neighbour)
|
||||
-- --
|
||||
-- -- score(chunk) = 1 / (1 + player + base)
|
||||
-- --
|
||||
-- -- The iteration is over a square region centered around the chunk for which the calculation is done,
|
||||
-- -- and includes the central chunk as well. distance is the Manhattan distance, and ^ signifies exponentiation.
|
||||
-- building_coefficient = 0.1,
|
||||
-- other_base_coefficient = 2.0,
|
||||
-- neighbouring_chunk_coefficient = 0.5,
|
||||
-- neighbouring_base_chunk_coefficient = 0.4,
|
||||
|
||||
-- -- A chunk has to have at most this much percent unbuildable tiles for it to be considered a candidate.
|
||||
-- -- This is to avoid chunks full of water to be marked as candidates.
|
||||
-- max_colliding_tiles_coefficient = 0.9,
|
||||
|
||||
-- -- Size of the group that goes to build new base (in game this is multiplied by the
|
||||
-- -- evolution factor).
|
||||
-- settler_group_min_size = 5,
|
||||
-- settler_group_max_size = 20,
|
||||
|
||||
-- -- Ticks to expand to a single
|
||||
-- -- position for a base is used.
|
||||
-- --
|
||||
-- -- cooldown is calculated as follows:
|
||||
-- -- cooldown = lerp(max_expansion_cooldown, min_expansion_cooldown, -e^2 + 2 * e),
|
||||
-- -- where lerp is the linear interpolation function, and e is the current evolution factor.
|
||||
-- min_expansion_cooldown = 4 * 3600,
|
||||
-- max_expansion_cooldown = 60 * 3600
|
||||
-- },
|
||||
|
||||
-- unit_group=
|
||||
-- {
|
||||
-- -- pollution triggered group waiting time is a random time between min and max gathering time
|
||||
-- min_group_gathering_time = 3600,
|
||||
-- max_group_gathering_time = 10 * 3600,
|
||||
-- -- after the gathering is finished the group can still wait for late members,
|
||||
-- -- but it doesn't accept new ones anymore
|
||||
-- max_wait_time_for_late_members = 2 * 3600,
|
||||
-- -- limits for group radius (calculated by number of numbers)
|
||||
-- max_group_radius = 30.0,
|
||||
-- min_group_radius = 5.0,
|
||||
-- -- when a member falls behind the group he can speedup up till this much of his regular speed
|
||||
-- max_member_speedup_when_behind = 1.4,
|
||||
-- -- When a member gets ahead of its group, it will slow down to at most this factor of its speed
|
||||
-- max_member_slowdown_when_ahead = 0.6,
|
||||
-- -- When members of a group are behind, the entire group will slow down to at most this factor of its max speed
|
||||
-- max_group_slowdown_factor = 0.3,
|
||||
-- -- If a member falls behind more than this times the group radius, the group will slow down to max_group_slowdown_factor
|
||||
-- max_group_member_fallback_factor = 3,
|
||||
-- -- If a member falls behind more than this time the group radius, it will be removed from the group.
|
||||
-- member_disown_distance = 10,
|
||||
-- tick_tolerance_when_member_arrives = 60,
|
||||
|
||||
-- -- Maximum number of automatically created unit groups gathering for attack at any time.
|
||||
-- max_gathering_unit_groups = 30,
|
||||
|
||||
-- -- Maximum size of an attack unit group. This only affects automatically-created unit groups;
|
||||
-- -- manual groups created through the API are unaffected.
|
||||
-- max_unit_group_size = 200
|
||||
-- },
|
||||
|
||||
-- steering=
|
||||
-- {
|
||||
-- default=
|
||||
-- {
|
||||
-- -- not including the radius of the unit
|
||||
-- radius = 1.2,
|
||||
-- separation_force = 0.005,
|
||||
-- separation_factor = 1.2,
|
||||
-- force_unit_fuzzy_goto_behavior = false
|
||||
-- },
|
||||
-- moving=
|
||||
-- {
|
||||
-- radius = 3,
|
||||
-- separation_force = 0.01,
|
||||
-- separation_factor = 3,
|
||||
-- -- used only for special 'to look good' purposes (like in trailer)
|
||||
-- force_unit_fuzzy_goto_behavior = false
|
||||
-- }
|
||||
-- },
|
||||
|
||||
-- path_finder=
|
||||
-- {
|
||||
-- -- defines whether we prefer forward (>1) or backward (<-1) or symmetrical (1) search
|
||||
-- fwd2bwd_ratio = 1,
|
||||
-- -- when comparing nodes in open which one to check next
|
||||
-- -- heuristic value is multiplied by this ratio
|
||||
-- -- the higher the number the more is the search directed directly towards the goal
|
||||
-- goal_pressure_ratio = 2,
|
||||
-- -- How many nodes can be expanded at most per tick.
|
||||
-- max_steps_worked_per_tick = 1000,
|
||||
-- -- How much work each patfinding job is allowed to do per tick.
|
||||
-- max_work_done_per_tick = 8000,
|
||||
-- -- path cache setings
|
||||
-- use_path_cache = true,
|
||||
-- -- number of elements in the cache
|
||||
-- short_cache_size = 5,
|
||||
-- long_cache_size = 25,
|
||||
-- -- minimal distance to goal for path to be searched in short path cache
|
||||
-- short_cache_min_cacheable_distance = 10,
|
||||
-- -- minimal number of algorithm steps for path to be inserted into the short path cache
|
||||
-- short_cache_min_algo_steps_to_cache = 50,
|
||||
-- -- minimal distance to goal for path to be searched in long path cache
|
||||
-- long_cache_min_cacheable_distance = 30,
|
||||
-- -- when searching for connection to path cache path, search at most for this number of steps times the initial estimate
|
||||
-- cache_max_connect_to_cache_steps_multiplier = 100,
|
||||
-- -- when looking for path from cache make sure it doesn't start too far from requested start in relative distance terms
|
||||
-- cache_accept_path_start_distance_ratio = 0.2,
|
||||
-- -- when looking for path from cache make sure it doesn't end too far from requested end
|
||||
-- -- this is typically higher than accept value for the start because the end target can be moving
|
||||
-- cache_accept_path_end_distance_ratio = 0.15,
|
||||
-- -- Same as cache_accept_path_start_distance_ratio, but used for negative cache queries
|
||||
-- negative_cache_accept_path_start_distance_ratio = 0.3,
|
||||
-- -- Same as cache_accept_path_end_distance_ratio, but used for negative cache queries
|
||||
-- negative_cache_accept_path_end_distance_ratio = 0.3,
|
||||
-- -- when assigning rating to the best path this * start distances is considered
|
||||
-- cache_path_start_distance_rating_multiplier = 10,
|
||||
-- -- when assigning rating to the best path this * end distances is considered
|
||||
-- -- this is typically higher than value for the start to achieve better path end quality
|
||||
-- cache_path_end_distance_rating_multiplier = 20,
|
||||
|
||||
-- -- somewhere along the path is stuck enemy we need to avoid
|
||||
-- -- this is mainly to handle situations when units have arrived and are attacking the target
|
||||
-- -- then units further in the back will use this and run around the target
|
||||
-- stale_enemy_with_same_destination_collision_penalty = 30,
|
||||
-- -- if there is a moving unit further than this we don't really care
|
||||
-- ignore_moving_enemy_collision_distance = 5,
|
||||
-- -- enemy is not moving/or is too close and has different destination
|
||||
-- enemy_with_different_destination_collision_penalty = 30,
|
||||
-- -- simplification for now - collision with everything else is this
|
||||
-- general_entity_collision_penalty = 10,
|
||||
-- -- collision penalty for successors of positions that require destroy to reach
|
||||
-- general_entity_subsequent_collision_penalty = 3,
|
||||
-- -- Collision penalty for collisions in the extended bounding box but outside the entity's actual bounding box
|
||||
-- extended_collision_penalty = 3,
|
||||
-- -- uptil this amount any client will be served by the path finder (no estimate on the path length)
|
||||
-- max_clients_to_accept_any_new_request = 10,
|
||||
-- -- from max_clients_to_accept_any_new_request till this one only those that have a short estimate will be served
|
||||
-- max_clients_to_accept_short_new_request = 100,
|
||||
-- -- this is the 'threshold' to decide what is short and what is not
|
||||
-- direct_distance_to_consider_short_request = 100,
|
||||
-- -- if a short request takes more than this many steps, it will be rescheduled as a long request
|
||||
-- short_request_max_steps = 1000,
|
||||
-- -- How many steps will be allocated to short requests each tick, as a ratio of all available steps per tick
|
||||
-- short_request_ratio = 0.5,
|
||||
-- -- absolute minimum of steps that will be performed for every path find request no matter what
|
||||
-- min_steps_to_check_path_find_termination = 2000,
|
||||
-- -- if the amount of steps is higher than this times estimate of start to goal then path finding is terminated
|
||||
-- start_to_goal_cost_multiplier_to_terminate_path_find = 2000.0,
|
||||
-- -- When the number of waiting clients exceeds certain values, the per-tick work limit will be increased by the
|
||||
-- -- given multiplier. overload_levels gives the threshold values, overload_multipliers gives the multipliers.
|
||||
-- -- overload_levels and overload_multipliers must be the same length.
|
||||
-- overload_levels = {0, 100, 500},
|
||||
-- overload_multipliers = {2, 3, 4}
|
||||
-- },
|
||||
|
||||
-- -- If a behavior fails this many times, the enemy (or enemy group)
|
||||
-- -- is destroyed.
|
||||
-- -- This solves biters stuck within their own base.
|
||||
-- max_failed_behavior_count = 3,
|
||||
|
||||
-- -- These can't be changed through game.map_settings - you must use game.difficulty_settings
|
||||
-- difficulty_settings =
|
||||
-- {
|
||||
-- recipe_difficulty = defines.difficulty_settings.recipe_difficulty.normal,
|
||||
-- technology_difficulty = defines.difficulty_settings.technology_difficulty.normal,
|
||||
-- technology_price_multiplier = 1,
|
||||
-- research_queue_setting = 'after-victory'
|
||||
-- }
|
||||
-- }
|
||||
-- })
|
285
maps/pirates/roles/classes.lua
Normal file
285
maps/pirates/roles/classes.lua
Normal file
@ -0,0 +1,285 @@
|
||||
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
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 CoreData = require 'maps.pirates.coredata'
|
||||
-- local Server = require 'utils.server'
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
DECKHAND = 1,
|
||||
FISHERMAN = 2,
|
||||
SCOUT = 3,
|
||||
SAMURAI = 4,
|
||||
MERCHANT = 5,
|
||||
SHORESMAN = 6,
|
||||
BOATSWAIN = 7,
|
||||
PROSPECTOR = 8,
|
||||
LUMBERJACK = 9,
|
||||
MASTER_ANGLER = 10,
|
||||
WOOD_LORD = 11,
|
||||
CHIEF_EXCAVATOR = 12,
|
||||
HATAMOTO = 13,
|
||||
IRON_LEG = 14,
|
||||
QUARTERMASTER = 15,
|
||||
DREDGER = 16,
|
||||
SMOLDERING = 17,
|
||||
GOURMET = 18,
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
Public.Class_List = {
|
||||
enum.DECKHAND,
|
||||
enum.FISHERMAN,
|
||||
enum.SCOUT,
|
||||
enum.SAMURAI,
|
||||
enum.MERCHANT,
|
||||
enum.SHORESMAN,
|
||||
enum.BOATSWAIN,
|
||||
enum.PROSPECTOR,
|
||||
enum.LUMBERJACK,
|
||||
enum.MASTER_ANGLER,
|
||||
enum.WOOD_LORD,
|
||||
enum.CHIEF_EXCAVATOR,
|
||||
enum.HATAMOTO,
|
||||
enum.IRON_LEG,
|
||||
enum.QUARTERMASTER,
|
||||
enum.DREDGER,
|
||||
enum.SMOLDERING,
|
||||
enum.GOURMET,
|
||||
}
|
||||
|
||||
Public.display_form = {
|
||||
[enum.DECKHAND] = 'Deckhand',
|
||||
[enum.FISHERMAN] = 'Fisherman',
|
||||
[enum.SCOUT] = 'Scout',
|
||||
[enum.SAMURAI] = 'Samurai',
|
||||
[enum.MERCHANT] = 'Merchant',
|
||||
[enum.SHORESMAN] = 'Shoresman',
|
||||
[enum.BOATSWAIN] = 'Boatswain',
|
||||
[enum.PROSPECTOR] = 'Prospector',
|
||||
[enum.LUMBERJACK] = 'Lumberjack',
|
||||
[enum.MASTER_ANGLER] = 'Master Angler',
|
||||
[enum.WOOD_LORD] = 'Lord of the Woods',
|
||||
[enum.CHIEF_EXCAVATOR] = 'Chief Excavator',
|
||||
[enum.HATAMOTO] = 'Hatamoto',
|
||||
[enum.IRON_LEG] = 'Iron Leg',
|
||||
[enum.QUARTERMASTER] = 'Quartermaster',
|
||||
[enum.DREDGER] = 'Dredger',
|
||||
[enum.SMOLDERING] = 'Smoldering',
|
||||
[enum.GOURMET] = 'Gourmet',
|
||||
}
|
||||
Public.explanation = {
|
||||
[enum.DECKHAND] = 'They move faster and generate ore for the cabin whilst onboard above deck, but move slower offboard.',
|
||||
[enum.FISHERMAN] = 'They fish at greater distance.',
|
||||
[enum.SCOUT] = 'They are faster, but frail and deal less damage.',
|
||||
[enum.SAMURAI] = 'They are tough, and *with no weapon equipped* fight well by melee, but poorly otherwise.',
|
||||
[enum.MERCHANT] = 'They generate 40 doubloons per league.',
|
||||
[enum.SHORESMAN] = 'They move slightly faster and generate ore for the cabin whilst offboard, but move slower onboard.',
|
||||
[enum.BOATSWAIN] = 'They move faster and generate ore for the cabin whilst below deck, but move slower offboard.',
|
||||
[enum.PROSPECTOR] = 'They find more resources when handmining ore.',
|
||||
[enum.LUMBERJACK] = 'They find more resources when chopping trees.',
|
||||
[enum.MASTER_ANGLER] = 'They fish at much greater distance, and catch more.',
|
||||
[enum.WOOD_LORD] = 'They find many more resources when chopping trees.',
|
||||
[enum.CHIEF_EXCAVATOR] = 'They find many more resources when handmining ore.',
|
||||
[enum.HATAMOTO] = 'They are very tough, and *with no weapon equipped* fight well by melee, but poorly otherwise.',
|
||||
[enum.IRON_LEG] = 'They are very resistant to damage when carrying 3500 iron ore.',
|
||||
[enum.QUARTERMASTER] = 'They give nearby crewmates extra physical attack, and generate ore for the cabin for each one.',
|
||||
[enum.DREDGER] = 'They find surprising items when they fish.',
|
||||
[enum.SMOLDERING] = 'They periodically convert wood into coal, if they have less than 50 coal.',
|
||||
[enum.GOURMET] = 'They generate ore for the cabin by eating fish in fancy locations.',
|
||||
}
|
||||
|
||||
Public.class_unlocks = {
|
||||
[enum.FISHERMAN] = {enum.MASTER_ANGLER},
|
||||
[enum.LUMBERJACK] = {enum.WOOD_LORD},
|
||||
-- [enum.PROSPECTOR] = {enum.CHIEF_EXCAVATOR}, --breaks the resource pressure in the game too strongly I think
|
||||
[enum.SAMURAI] = {enum.HATAMOTO},
|
||||
[enum.MASTER_ANGLER] = {enum.DREDGER},
|
||||
}
|
||||
|
||||
Public.class_purchase_requirement = {
|
||||
[enum.MASTER_ANGLER] = enum.FISHERMAN,
|
||||
[enum.WOOD_LORD] = enum.LUMBERJACK,
|
||||
-- [enum.CHIEF_EXCAVATOR] = enum.PROSPECTOR,
|
||||
[enum.HATAMOTO] = enum.SAMURAI,
|
||||
[enum.DREDGER] = enum.MASTER_ANGLER,
|
||||
}
|
||||
|
||||
function Public.initial_class_pool()
|
||||
return {
|
||||
enum.DECKHAND,
|
||||
enum.DECKHAND, --good for afk players
|
||||
enum.SHORESMAN,
|
||||
enum.SHORESMAN,
|
||||
enum.QUARTERMASTER,
|
||||
enum.FISHERMAN,
|
||||
enum.SCOUT,
|
||||
enum.SAMURAI,
|
||||
-- enum.MERCHANT, --not interesting, breaks coin economy
|
||||
enum.BOATSWAIN,
|
||||
enum.PROSPECTOR,
|
||||
enum.LUMBERJACK,
|
||||
enum.IRON_LEG,
|
||||
enum.SMOLDERING,
|
||||
enum.GOURMET,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
function Public.assign_class(player_index, class, self_assigned)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local player = game.players[player_index]
|
||||
|
||||
if not memory.classes_table then memory.classes_table = {} end
|
||||
|
||||
if memory.classes_table[player_index] == class then
|
||||
Common.notify_player_error(player, 'Class error: You\'re already a ' .. Public.display_form[class] .. '.')
|
||||
return false
|
||||
end
|
||||
|
||||
if Utils.contains(memory.spare_classes, class) then -- verify that one is spare
|
||||
|
||||
Public.try_renounce_class(player, false)
|
||||
|
||||
memory.classes_table[player_index] = class
|
||||
|
||||
local force = memory.force
|
||||
if force and force.valid then
|
||||
local message
|
||||
if self_assigned then
|
||||
message = '%s took the spare class %s. ([font=scenario-message-dialog]%s[/font])'
|
||||
Common.notify_force_light(force,string.format(message, player.name, Public.display_form[memory.classes_table[player_index]], Public.explanation[memory.classes_table[player_index]]))
|
||||
else
|
||||
message = 'A spare %s class was given to %s. [font=scenario-message-dialog](%s)[/font]'
|
||||
Common.notify_force_light(force,string.format(message, Public.display_form[memory.classes_table[player_index]], player.name, Public.explanation[memory.classes_table[player_index]]))
|
||||
end
|
||||
end
|
||||
|
||||
memory.spare_classes = Utils.ordered_table_with_single_value_removed(memory.spare_classes, class)
|
||||
return true
|
||||
else
|
||||
Common.notify_player_error(player, 'Class error: No spare class of that type is available.')
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Public.try_renounce_class(player, whisper_failure_message, override_message)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local force = memory.force
|
||||
if force and force.valid and player and player.index then
|
||||
if memory.classes_table and memory.classes_table[player.index] then
|
||||
if force and force.valid then
|
||||
if override_message then
|
||||
Common.notify_force_light(force,string.format(override_message, Public.display_form[memory.classes_table[player.index]]))
|
||||
else
|
||||
Common.notify_force_light(force,string.format('%s gave up %s.', player.name, Public.display_form[memory.classes_table[player.index]])) --shorter for less spam
|
||||
-- Common.notify_force_light(force,string.format('%s gave up the class %s.', player.name, Public.display_form[memory.classes_table[player.index]]))
|
||||
end
|
||||
end
|
||||
|
||||
memory.spare_classes[#memory.spare_classes + 1] = memory.classes_table[player.index]
|
||||
memory.classes_table[player.index] = nil
|
||||
elseif whisper_failure_message then
|
||||
Common.notify_player_error(player, 'Class error: You don\'t have any class to give up.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.generate_class_for_sale()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
-- if #memory.available_classes_pool == 0 then
|
||||
-- -- memory.available_classes_pool = Public.initial_class_pool() --reset to initial state
|
||||
-- -- turned off as this makes too many classes
|
||||
-- end
|
||||
|
||||
local class
|
||||
if #memory.available_classes_pool > 0 then
|
||||
class = memory.available_classes_pool[Math.random(#memory.available_classes_pool)]
|
||||
end
|
||||
|
||||
return class
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.class_ore_grant(player, how_much, disable_scaling)
|
||||
local count
|
||||
if disable_scaling then
|
||||
count = Math.ceil(how_much)
|
||||
else
|
||||
count = Math.ceil(how_much * Balance.class_resource_scale())
|
||||
end
|
||||
if Math.random(4) == 1 then
|
||||
Common.flying_text_small(player.surface, player.position, '[color=0.85,0.58,0.37]+' .. count .. '[/color]')
|
||||
Common.give_items_to_crew{{name = 'copper-ore', count = count}}
|
||||
else
|
||||
Common.flying_text_small(player.surface, player.position, '[color=0.7,0.8,0.8]+' .. count .. '[/color]')
|
||||
Common.give_items_to_crew{{name = 'iron-ore', count = count}}
|
||||
end
|
||||
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
|
||||
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
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
|
||||
|
||||
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 tile = player.surface.get_tile(player.position)
|
||||
if tile.valid then
|
||||
local multiplier = 0
|
||||
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.8
|
||||
elseif tile.name == CoreData.enemy_landing_tile then
|
||||
multiplier = 0.33
|
||||
elseif tile.name == CoreData.static_boat_floor then
|
||||
multiplier = 0.1
|
||||
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.max(0.2, Math.min(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, 10 * multiplier, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.add(defines.events.on_player_used_capsule, class_on_player_used_capsule)
|
||||
|
||||
return Public
|
650
maps/pirates/roles/roles.lua
Normal file
650
maps/pirates/roles/roles.lua
Normal file
@ -0,0 +1,650 @@
|
||||
|
||||
local Session = require 'utils.datastore.session_data'
|
||||
local Antigrief = require 'utils.antigrief'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
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 CoreData = require 'maps.pirates.coredata'
|
||||
local Server = require 'utils.server'
|
||||
local Classes = require 'maps.pirates.roles.classes'
|
||||
|
||||
local Public = {}
|
||||
local privilege_levels = {
|
||||
NORMAL = 1,
|
||||
OFFICER = 2,
|
||||
CAPTAIN = 3
|
||||
}
|
||||
Public.privilege_levels = privilege_levels
|
||||
|
||||
|
||||
--== Roles — General ==--
|
||||
|
||||
function Public.reset_officers()
|
||||
local memory = Memory.get_crew_memory()
|
||||
memory.officers_table = {}
|
||||
end
|
||||
|
||||
function Public.make_officer(captain, player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local force = memory.force
|
||||
|
||||
if Utils.contains(Common.crew_get_crew_members(), player) then
|
||||
if (not (captain.index == player.index)) then
|
||||
if Common.validate_player(player) then
|
||||
memory.officers_table[player.index] = true
|
||||
|
||||
local message = (captain.name .. ' made ' .. player.name .. ' an officer.')
|
||||
Common.notify_force_light(force, message)
|
||||
Public.update_privileges(player)
|
||||
else
|
||||
Common.notify_player_error(captain, 'Command error: Player is invalid.')
|
||||
return false
|
||||
end
|
||||
else
|
||||
Common.notify_player_error(captain, 'Command error: Can\'t promote yourself to officer.')
|
||||
return false
|
||||
end
|
||||
else
|
||||
Common.notify_player_error(captain, 'Command error: Player is not a crewmember.')
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Public.unmake_officer(captain, player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local force = memory.force
|
||||
|
||||
if Utils.contains(Common.crew_get_crew_members(), player) then
|
||||
if memory.officers_table[player.index] then
|
||||
memory.officers_table[player.index] = nil
|
||||
|
||||
local message = (captain.name .. ' unmade ' .. player.name .. ' an officer.')
|
||||
Common.notify_force_light(force, message)
|
||||
Public.update_privileges(player)
|
||||
return true
|
||||
else
|
||||
Common.notify_player_error(captain, 'Command error: Player isn\'t an officer.')
|
||||
return false
|
||||
end
|
||||
else
|
||||
Common.notify_player_error(captain, 'Command error: Player is not a crewmember.')
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function Public.revoke_class(captain, player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local force = memory.force
|
||||
|
||||
if force and force.valid and player.index and memory.classes_table[player.index] then
|
||||
memory.spare_classes[#memory.spare_classes + 1] = memory.classes_table[player.index]
|
||||
memory.classes_table[player.index] = nil
|
||||
|
||||
Common.notify_force_light(force, string.format('%s revoked %s from %s.', captain.name, Classes.display_form[memory.classes_table[player.index]]), player.name)
|
||||
end
|
||||
end
|
||||
|
||||
function Public.tag_text(player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local str = ''
|
||||
local tags = {}
|
||||
|
||||
if memory.id ~= 0 and Common.is_captain(player) then
|
||||
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
|
||||
tags[#tags + 1] = 'Officer'
|
||||
end
|
||||
|
||||
local classes_table = memory.classes_table
|
||||
if classes_table and classes_table[player.index] then
|
||||
tags[#tags + 1] = Classes.display_form[classes_table[player.index]]
|
||||
end
|
||||
|
||||
for i, t in ipairs(tags) do
|
||||
if i>1 then str = str .. ', ' end
|
||||
str = str .. t
|
||||
end
|
||||
|
||||
if (not (str == '')) then str = '[' .. str .. ']' end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
function Public.update_tags(player)
|
||||
|
||||
local str = Public.tag_text(player)
|
||||
player.tag = str
|
||||
end
|
||||
|
||||
-- function Public.get_classes_print_string()
|
||||
-- local str = 'Current class Descriptions:'
|
||||
|
||||
-- for i, class in ipairs(Classes.Class_List) do
|
||||
-- str = str .. '\n' .. Classes.display_form[class] .. ': ' .. Classes.explanation[class] .. ''
|
||||
-- end
|
||||
|
||||
-- return str
|
||||
-- end
|
||||
|
||||
function Public.get_class_print_string(class)
|
||||
|
||||
for _, class2 in ipairs(Classes.Class_List) do
|
||||
if Classes.display_form[class2]:lower() == class:lower() then
|
||||
local str = ''
|
||||
str = str .. Classes.display_form[class2] .. ': '
|
||||
if Classes.class_purchase_requirement[class2] then
|
||||
str = str .. 'An upgrade of ' .. Classes.display_form[Classes.class_purchase_requirement[class2]] .. '. '
|
||||
end
|
||||
str = str .. Classes.explanation[class2]
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
if class:lower() == 'officer' then
|
||||
return 'Officer: Assigned by the captain, officers can use the Captain\'s shop and access privileged chests.'
|
||||
end
|
||||
|
||||
if class:lower() == 'captain' then
|
||||
return 'Captain: Has executive power to undock the ship, purchase items, and various other special actions. When the game assigns a captain, it gives priority to those who have been playing the longest as a non-captain.'
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function Public.player_privilege_level(player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if memory.id ~= 0 and Common.is_captain(player) then
|
||||
return Public.privilege_levels.CAPTAIN
|
||||
elseif memory.officers_table and memory.officers_table[player.index] then
|
||||
return Public.privilege_levels.OFFICER
|
||||
else
|
||||
return Public.privilege_levels.NORMAL
|
||||
end
|
||||
end
|
||||
|
||||
function Public.make_captain(player)
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if memory.playerindex_captain then
|
||||
Public.update_privileges(game.players[memory.playerindex_captain])
|
||||
end
|
||||
|
||||
memory.playerindex_captain = player.index
|
||||
global_memory.playerindex_to_captainhood_priority[player.index] = nil
|
||||
memory.captain_acceptance_timer = nil
|
||||
|
||||
Public.reset_officers()
|
||||
Public.update_privileges(player)
|
||||
end
|
||||
|
||||
function Public.player_confirm_captainhood(player)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local captain_index = memory.playerindex_captain
|
||||
|
||||
if not (player.index == captain_index) then
|
||||
Common.notify_player_error(player, 'Command error: You\'re not the captain.')
|
||||
else
|
||||
if memory.captain_acceptance_timer then
|
||||
memory.captain_acceptance_timer = nil
|
||||
|
||||
local force = player.force
|
||||
if force and force.valid then
|
||||
local message = (player.name .. ' accepted the role of captain.')
|
||||
Common.notify_force(force, message)
|
||||
Server.to_discord_embed_raw(CoreData.comfy_emojis.derp .. '[' .. memory.name .. '] ' .. message)
|
||||
end
|
||||
else
|
||||
Common.notify_player_expected(player, 'Command error: You\'re not temporary, so you don\'t need to accept.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.player_left_so_redestribute_roles(player)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
if player and player.index then
|
||||
if Common.is_captain(player) then
|
||||
Public.assign_captain_based_on_priorities()
|
||||
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
|
||||
-- memory.officers_table[player.index] = nil
|
||||
-- end
|
||||
end
|
||||
|
||||
Classes.try_renounce_class(player, false, "A %s class is now spare.")
|
||||
end
|
||||
|
||||
|
||||
function Public.renounce_captainhood(player)
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if #Common.crew_get_crew_members() == 1 then
|
||||
Common.notify_player_error(player, 'Command error: But you\'re the only crew member...')
|
||||
else
|
||||
|
||||
local force = memory.force
|
||||
global_memory.playerindex_to_captainhood_priority[player.index] = nil
|
||||
if force and force.valid then
|
||||
local message = (player.name .. ' renounces their title of captain.')
|
||||
Common.notify_force(force, message)
|
||||
Server.to_discord_embed_raw(CoreData.comfy_emojis.ree1 .. '[' .. memory.name .. '] ' .. message)
|
||||
end
|
||||
|
||||
Public.assign_captain_based_on_priorities(player.index)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
memory.officers_table[player.index] = nil
|
||||
|
||||
local message = (player.name .. ' resigns as an officer.')
|
||||
Common.notify_force(force, message)
|
||||
Server.to_discord_embed_raw(CoreData.comfy_emojis.ree1 .. '[' .. memory.name .. '] ' .. message)
|
||||
else
|
||||
log('Error: player tried to resign as officer despite not being one.')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.confirm_captain_exists(player_to_make_captain_otherwise)
|
||||
local memory = Memory.get_crew_memory()
|
||||
-- Currently this catches an issue where a crew drops to zero players, and then someone else joins.
|
||||
|
||||
if (memory.id and memory.id > 0 and memory.crewstatus and memory.crewstatus == 'adventuring') and (not (memory.playerindex_captain and game.players[memory.playerindex_captain] and Common.validate_player(game.players[memory.playerindex_captain]))) then --fixme: enum hacked
|
||||
if player_to_make_captain_otherwise then
|
||||
Public.make_captain(player_to_make_captain_otherwise)
|
||||
-- game.print('Auto-reassigning captain.')
|
||||
else
|
||||
log('Error: Couldn\'t make a captain.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.pass_captainhood(player, player_to_pass_to)
|
||||
-- local global_memory = Memory.get_global_memory()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local force = memory.force
|
||||
if not (force and force.valid) then return end
|
||||
local message = string.format("%s has passed their captainhood to %s.", player.name, player_to_pass_to.name)
|
||||
Common.notify_force(force, message)
|
||||
Server.to_discord_embed_raw(CoreData.comfy_emojis.spurdo .. '[' .. memory.name .. '] ' .. message)
|
||||
|
||||
Public.make_captain(player_to_pass_to)
|
||||
end
|
||||
|
||||
function Public.afk_player_tick(player)
|
||||
-- local global_memory = Memory.get_global_memory()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if Common.is_captain(player) and #Common.crew_get_nonafk_crew_members() > 0 then
|
||||
|
||||
local force = memory.force
|
||||
if force and force.valid then
|
||||
local message = string.format(player.name .. ' was afk.')
|
||||
Common.notify_force(force, message)
|
||||
Server.to_discord_embed_raw(CoreData.comfy_emojis.loops .. '[' .. memory.name .. '] ' .. message)
|
||||
end
|
||||
|
||||
if #Common.crew_get_nonafk_crew_members() == 1 then --don't need to bounce it around
|
||||
Public.make_captain(Common.crew_get_nonafk_crew_members()[1])
|
||||
else
|
||||
Public.assign_captain_based_on_priorities()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.assign_captain_based_on_priorities(excluded_player_index)
|
||||
excluded_player_index = excluded_player_index or nil
|
||||
|
||||
local global_memory = Memory.get_global_memory()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local crew_members = memory.crewplayerindices
|
||||
|
||||
if not (crew_members and #crew_members > 0) then return end
|
||||
|
||||
local only_found_afk_players = true
|
||||
local best_priority_so_far = -1
|
||||
local captain_index = nil
|
||||
local captain_name = nil
|
||||
|
||||
for _, player_index in pairs(crew_members) do
|
||||
local player = game.players[player_index]
|
||||
|
||||
if Common.validate_player(player) and not (player.index == excluded_player_index) then
|
||||
|
||||
local player_active = Utils.contains(Common.crew_get_nonafk_crew_members(), player)
|
||||
|
||||
-- prefer non-afk players:
|
||||
if only_found_afk_players or player_active then
|
||||
only_found_afk_players = player_active
|
||||
|
||||
local player_priority = global_memory.playerindex_to_captainhood_priority[player_index]
|
||||
if player_priority and player_priority > best_priority_so_far then
|
||||
best_priority_so_far = player_priority
|
||||
captain_index = player_index
|
||||
captain_name = player.name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local force = memory.force
|
||||
if not (force and force.valid) then return end
|
||||
|
||||
if not captain_index then
|
||||
captain_index = crew_members[1]
|
||||
captain_name = game.players[captain_index].name
|
||||
Common.notify_force(force,'Looking for a suitable captain...')
|
||||
end
|
||||
|
||||
if captain_index then
|
||||
local player = game.players[captain_index]
|
||||
if player and Common.validate_player(player) then
|
||||
Public.make_captain(player)
|
||||
-- this sets memory.captain_acceptance_timer = nil so now we must reset that after this function
|
||||
end
|
||||
end
|
||||
|
||||
if #Common.crew_get_crew_members() > 1 then
|
||||
local messages = {
|
||||
"would you like to be captain?",
|
||||
"would you like to be captain?",
|
||||
"captain?",
|
||||
"is it your turn to be captain?",
|
||||
}
|
||||
local message = captain_name .. ', ' .. messages[Math.random(#messages)]
|
||||
Common.notify_force_light(force, message .. ' If yes say /ok')
|
||||
-- Server.to_discord_embed_raw('[' .. memory.name .. ']' .. CoreData.comfy_emojis.spurdo .. ' ' .. message)
|
||||
memory.captain_acceptance_timer = 72 --tuned
|
||||
else
|
||||
memory.captain_acceptance_timer = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.captain_requisition(captain_index)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local any_taken = false
|
||||
|
||||
local items_to_req = {'coin', 'uranium-235'}
|
||||
|
||||
local item_count_table = {}
|
||||
for _, i in pairs(items_to_req) do
|
||||
item_count_table[i] = 0
|
||||
end
|
||||
|
||||
local crew_members = memory.crewplayerindices
|
||||
local captain = game.players[captain_index]
|
||||
if not (captain and crew_members) then return end
|
||||
|
||||
local captain_inv = captain.get_inventory(defines.inventory.character_main)
|
||||
if captain_inv and captain_inv.valid then
|
||||
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
|
||||
local inv = player.get_inventory(defines.inventory.character_main)
|
||||
if inv and inv.valid then
|
||||
for _, i in pairs(items_to_req) do
|
||||
local amount = inv.get_item_count(i)
|
||||
if amount and amount > 0 then
|
||||
inv.remove{name=i, count=amount}
|
||||
captain_inv.insert{name=i, count=amount}
|
||||
item_count_table[i] = item_count_table[i] + amount
|
||||
any_taken = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local cursor_stack = player.cursor_stack
|
||||
if cursor_stack and cursor_stack.valid_for_read then
|
||||
for _, i in pairs(items_to_req) do
|
||||
if cursor_stack.name == i then
|
||||
local cursor_stack_count = cursor_stack.count
|
||||
if cursor_stack_count > 0 then
|
||||
cursor_stack.count = 0
|
||||
captain_inv.insert{name=i, count = cursor_stack_count}
|
||||
item_count_table[i] = item_count_table[i] + cursor_stack_count
|
||||
any_taken = true
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if any_taken then
|
||||
local str = 'The captain requisitioned '
|
||||
local j = 1
|
||||
for i = 1, #items_to_req do
|
||||
local item = items_to_req[i]
|
||||
local count = item_count_table[item]
|
||||
if count > 0 then
|
||||
if j > 1 then
|
||||
if i == #items_to_req then
|
||||
str = str .. ' and '
|
||||
else
|
||||
str = str .. ', '
|
||||
end
|
||||
end
|
||||
local display_name = item
|
||||
if display_name == 'coin' then display_name = 'doubloons' end
|
||||
if count >= 1000 then
|
||||
str = str .. Utils.bignumber_abbrevform2(count) .. ' ' .. display_name
|
||||
else
|
||||
str = str .. count .. ' ' .. display_name
|
||||
end
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
str = str .. '.'
|
||||
Common.notify_force(memory.force, str)
|
||||
else
|
||||
Common.notify_player_error(captain, 'No important items found in crewmates\' inventories or cursor stacks.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.add_player_to_permission_group(player, group_override)
|
||||
-- local jailed = Jailed.get_jailed_table()
|
||||
-- local enable_permission_group_disconnect = WPT.get('disconnect_wagon')
|
||||
local session = Session.get_session_table()
|
||||
local AG = Antigrief.get()
|
||||
|
||||
local gulag = game.permissions.get_group('gulag')
|
||||
local tbl = gulag and gulag.players
|
||||
for i = 1, #tbl do
|
||||
if tbl[i].index == player.index then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- if player.admin then
|
||||
-- return
|
||||
-- end
|
||||
|
||||
local playtime = player.online_time
|
||||
if session and session[player.name] then
|
||||
playtime = player.online_time + session[player.name]
|
||||
end
|
||||
|
||||
-- if jailed[player.name] then
|
||||
-- return
|
||||
-- end
|
||||
|
||||
if not game.permissions.get_group('restricted_area') then
|
||||
local group = game.permissions.create_group('restricted_area')
|
||||
group.set_allows_action(defines.input_action.edit_permission_group, false)
|
||||
group.set_allows_action(defines.input_action.import_permissions_string, false)
|
||||
group.set_allows_action(defines.input_action.delete_permission_group, false)
|
||||
group.set_allows_action(defines.input_action.add_permission_group, false)
|
||||
group.set_allows_action(defines.input_action.admin_action, false)
|
||||
|
||||
group.set_allows_action(defines.input_action.cancel_craft, false)
|
||||
group.set_allows_action(defines.input_action.drop_item, false)
|
||||
group.set_allows_action(defines.input_action.drop_blueprint_record, false)
|
||||
group.set_allows_action(defines.input_action.build, false)
|
||||
group.set_allows_action(defines.input_action.build_rail, false)
|
||||
group.set_allows_action(defines.input_action.build_terrain, false)
|
||||
group.set_allows_action(defines.input_action.begin_mining, false)
|
||||
group.set_allows_action(defines.input_action.begin_mining_terrain, false)
|
||||
-- group.set_allows_action(defines.input_action.deconstruct, false) --pick up dead players
|
||||
group.set_allows_action(defines.input_action.activate_copy, false)
|
||||
group.set_allows_action(defines.input_action.activate_cut, false)
|
||||
group.set_allows_action(defines.input_action.activate_paste, false)
|
||||
group.set_allows_action(defines.input_action.upgrade, false)
|
||||
|
||||
group.set_allows_action(defines.input_action.grab_blueprint_record, false)
|
||||
if not CoreData.blueprint_library_allowed then
|
||||
group.set_allows_action(defines.input_action.open_blueprint_library_gui, false)
|
||||
end
|
||||
if not CoreData.blueprint_importing_allowed then
|
||||
group.set_allows_action(defines.input_action.import_blueprint_string, false)
|
||||
group.set_allows_action(defines.input_action.import_blueprint, false)
|
||||
end
|
||||
|
||||
group.set_allows_action(defines.input_action.open_gui, false)
|
||||
group.set_allows_action(defines.input_action.fast_entity_transfer, false)
|
||||
group.set_allows_action(defines.input_action.fast_entity_split, false)
|
||||
end
|
||||
|
||||
if not game.permissions.get_group('restricted_area_privileged') then
|
||||
local group = game.permissions.create_group('restricted_area_privileged')
|
||||
group.set_allows_action(defines.input_action.edit_permission_group, false)
|
||||
group.set_allows_action(defines.input_action.import_permissions_string, false)
|
||||
group.set_allows_action(defines.input_action.delete_permission_group, false)
|
||||
group.set_allows_action(defines.input_action.add_permission_group, false)
|
||||
group.set_allows_action(defines.input_action.admin_action, false)
|
||||
|
||||
group.set_allows_action(defines.input_action.cancel_craft, false)
|
||||
group.set_allows_action(defines.input_action.drop_item, false)
|
||||
group.set_allows_action(defines.input_action.drop_blueprint_record, false)
|
||||
group.set_allows_action(defines.input_action.build, false)
|
||||
group.set_allows_action(defines.input_action.build_rail, false)
|
||||
group.set_allows_action(defines.input_action.build_terrain, false)
|
||||
group.set_allows_action(defines.input_action.begin_mining, false)
|
||||
group.set_allows_action(defines.input_action.begin_mining_terrain, false)
|
||||
-- group.set_allows_action(defines.input_action.deconstruct, false) --pick up dead players
|
||||
group.set_allows_action(defines.input_action.activate_copy, false)
|
||||
group.set_allows_action(defines.input_action.activate_cut, false)
|
||||
group.set_allows_action(defines.input_action.activate_paste, false)
|
||||
group.set_allows_action(defines.input_action.upgrade, false)
|
||||
|
||||
group.set_allows_action(defines.input_action.grab_blueprint_record, false)
|
||||
if not CoreData.blueprint_library_allowed then
|
||||
group.set_allows_action(defines.input_action.open_blueprint_library_gui, false)
|
||||
end
|
||||
if not CoreData.blueprint_importing_allowed then
|
||||
group.set_allows_action(defines.input_action.import_blueprint_string, false)
|
||||
group.set_allows_action(defines.input_action.import_blueprint, false)
|
||||
end
|
||||
end
|
||||
|
||||
if not game.permissions.get_group('plebs') then
|
||||
local plebs_group = game.permissions.create_group('plebs')
|
||||
if not _DEBUG then
|
||||
plebs_group.set_allows_action(defines.input_action.edit_permission_group, false)
|
||||
plebs_group.set_allows_action(defines.input_action.import_permissions_string, false)
|
||||
plebs_group.set_allows_action(defines.input_action.delete_permission_group, false)
|
||||
plebs_group.set_allows_action(defines.input_action.add_permission_group, false)
|
||||
plebs_group.set_allows_action(defines.input_action.admin_action, false)
|
||||
|
||||
plebs_group.set_allows_action(defines.input_action.grab_blueprint_record, false)
|
||||
if not CoreData.blueprint_library_allowed then
|
||||
plebs_group.set_allows_action(defines.input_action.open_blueprint_library_gui, false)
|
||||
end
|
||||
if not CoreData.blueprint_importing_allowed then
|
||||
plebs_group.set_allows_action(defines.input_action.import_blueprint_string, false)
|
||||
plebs_group.set_allows_action(defines.input_action.import_blueprint, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not game.permissions.get_group('not_trusted') then
|
||||
local not_trusted = game.permissions.create_group('not_trusted')
|
||||
-- not_trusted.set_allows_action(defines.input_action.cancel_craft, false)
|
||||
not_trusted.set_allows_action(defines.input_action.edit_permission_group, false)
|
||||
not_trusted.set_allows_action(defines.input_action.import_permissions_string, false)
|
||||
not_trusted.set_allows_action(defines.input_action.delete_permission_group, false)
|
||||
not_trusted.set_allows_action(defines.input_action.add_permission_group, false)
|
||||
not_trusted.set_allows_action(defines.input_action.admin_action, false)
|
||||
-- not_trusted.set_allows_action(defines.input_action.drop_item, false)
|
||||
not_trusted.set_allows_action(defines.input_action.disconnect_rolling_stock, false)
|
||||
not_trusted.set_allows_action(defines.input_action.connect_rolling_stock, false)
|
||||
not_trusted.set_allows_action(defines.input_action.open_train_gui, false)
|
||||
not_trusted.set_allows_action(defines.input_action.open_train_station_gui, false)
|
||||
not_trusted.set_allows_action(defines.input_action.open_trains_gui, false)
|
||||
not_trusted.set_allows_action(defines.input_action.change_train_stop_station, false)
|
||||
not_trusted.set_allows_action(defines.input_action.change_train_wait_condition, false)
|
||||
not_trusted.set_allows_action(defines.input_action.change_train_wait_condition_data, false)
|
||||
not_trusted.set_allows_action(defines.input_action.drag_train_schedule, false)
|
||||
not_trusted.set_allows_action(defines.input_action.drag_train_wait_condition, false)
|
||||
not_trusted.set_allows_action(defines.input_action.go_to_train_station, false)
|
||||
not_trusted.set_allows_action(defines.input_action.remove_train_station, false)
|
||||
not_trusted.set_allows_action(defines.input_action.set_trains_limit, false)
|
||||
not_trusted.set_allows_action(defines.input_action.set_train_stopped, false)
|
||||
|
||||
not_trusted.set_allows_action(defines.input_action.grab_blueprint_record, false)
|
||||
if not CoreData.blueprint_library_allowed then
|
||||
not_trusted.set_allows_action(defines.input_action.open_blueprint_library_gui, false)
|
||||
end
|
||||
if not CoreData.blueprint_importing_allowed then
|
||||
not_trusted.set_allows_action(defines.input_action.import_blueprint_string, false)
|
||||
not_trusted.set_allows_action(defines.input_action.import_blueprint, false)
|
||||
end
|
||||
end
|
||||
|
||||
local group
|
||||
if group_override then
|
||||
group = game.permissions.get_group(group_override)
|
||||
else
|
||||
if AG.enabled and not player.admin and playtime < 5184000 then -- 24 hours
|
||||
group = game.permissions.get_group('not_trusted')
|
||||
else
|
||||
group = game.permissions.get_group('plebs')
|
||||
end
|
||||
end
|
||||
group.add_player(player)
|
||||
end
|
||||
|
||||
function Public.update_privileges(player)
|
||||
if not Common.validate_player_and_character(player) then
|
||||
return
|
||||
end
|
||||
|
||||
if string.sub(player.surface.name, 9, 17) == 'Crowsnest' or string.sub(player.surface.name, 9, 13) == 'Cabin' then
|
||||
if Public.player_privilege_level(player) >= Public.privilege_levels.OFFICER then
|
||||
return Public.add_player_to_permission_group(player, 'restricted_area_privileged')
|
||||
else
|
||||
return Public.add_player_to_permission_group(player, 'restricted_area')
|
||||
end
|
||||
else
|
||||
return Public.add_player_to_permission_group(player)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
333
maps/pirates/shop/captains.lua
Normal file
333
maps/pirates/shop/captains.lua
Normal file
@ -0,0 +1,333 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Loot = require 'maps.pirates.loot'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Upgrades = require 'maps.pirates.boat_upgrades'
|
||||
-- local Hold = require 'maps.pirates.surfaces.hold'
|
||||
local Crew = require 'maps.pirates.crew'
|
||||
local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local Dock = require 'maps.pirates.surfaces.dock'
|
||||
local CustomEvents = require 'maps.pirates.custom_events'
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
||||
|
||||
|
||||
--== Warning: If something only costs fuel, then we need to check the player can't buy it whilst they're dead
|
||||
|
||||
Public.main_shop_data_1 = {
|
||||
repair_cannons = {
|
||||
tooltip = 'Repair the cannons.',
|
||||
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},
|
||||
base_cost = {fuel = 3000},
|
||||
},
|
||||
new_boat_sloop_with_hold = {
|
||||
tooltip = 'Purchase a sloop (with hold).',
|
||||
what_you_get_sprite_buttons = {['utility/spawn_flag'] = false},
|
||||
base_cost = {fuel = 3500},
|
||||
},
|
||||
new_boat_cutter_with_hold = {
|
||||
tooltip = 'Purchase a cutter (with hold).',
|
||||
what_you_get_sprite_buttons = {['utility/spawn_flag'] = false},
|
||||
base_cost = {fuel = 5000},
|
||||
},
|
||||
-- buy_iron = {
|
||||
-- tooltip = 'Purchase 250 iron plates for 300 stored fuel.',
|
||||
-- what_you_get_sprite_buttons = {['item/iron-plate'] = 250},
|
||||
-- base_cost = {fuel = 300},
|
||||
-- },
|
||||
-- buy_copper = {
|
||||
-- tooltip = 'Purchase 250 copper plates for 300 stored fuel.',
|
||||
-- what_you_get_sprite_buttons = {['item/copper-plate'] = 250},
|
||||
-- base_cost = {fuel = 300},
|
||||
-- },
|
||||
-- sell_iron = {
|
||||
-- tooltip = 'Purchase 200 stored fuel for 2000 iron plates.',
|
||||
-- what_you_get_sprite_buttons = {['item/sulfur'] = 200},
|
||||
-- base_cost = {iron_plates = 2000},
|
||||
-- },
|
||||
-- sell_copper = {
|
||||
-- tooltip = 'Purchase 100 stored fuel for 2500 copper plates',
|
||||
-- what_you_get_sprite_buttons = {['item/sulfur'] = 100},
|
||||
-- base_cost = {copper_plates = 2500},
|
||||
-- },
|
||||
-- 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.',
|
||||
what_you_get_sprite_buttons = {['utility/status_working'] = false},
|
||||
base_cost = {coins = 5000, fuel = 500},
|
||||
},
|
||||
[Upgrades.enum.EXTRA_HOLD] = {
|
||||
tooltip = 'Upgrade the ship\'s hold.',
|
||||
what_you_get_sprite_buttons = {['item/steel-chest'] = false},
|
||||
base_cost = {coins = 10000, fuel = 2000},
|
||||
},
|
||||
[Upgrades.enum.UNLOCK_MERCHANTS] = {
|
||||
tooltip = 'Unlock merchant ships.',
|
||||
what_you_get_sprite_buttons = {['entity/market'] = false},
|
||||
base_cost = {coins = 10000, fuel = 2000},
|
||||
},
|
||||
[Upgrades.enum.ROCKETS_FOR_SALE] = {
|
||||
tooltip = 'Unlock rockets for sale at covered-up markets.',
|
||||
what_you_get_sprite_buttons = {['item/rocket-launcher'] = false},
|
||||
base_cost = {coins = 15000, fuel = 2000},
|
||||
},
|
||||
}
|
||||
|
||||
Public.main_shop_data_2 = {
|
||||
rail_signal = {
|
||||
tooltip = "100 signals, used to steer the boat one space in the Crow's Nest View.",
|
||||
what_you_get_sprite_buttons = {['item/rail-signal'] = 100},
|
||||
base_cost = {coins = 600, fuel = 50},
|
||||
},
|
||||
artillery_shell = {
|
||||
tooltip = '8 cannon shells.',
|
||||
what_you_get_sprite_buttons = {['item/artillery-shell'] = 8},
|
||||
base_cost = {coins = 800, fuel = 30},
|
||||
},
|
||||
artillery_remote = {
|
||||
tooltip = 'An artillery targeting remote.',
|
||||
what_you_get_sprite_buttons = {['item/artillery-targeting-remote'] = 1},
|
||||
base_cost = {coins = 12000, fuel = 2500},
|
||||
},
|
||||
-- buy_fast_loader = {
|
||||
-- tooltip = 'A fast loader for 500 stored fuel.',
|
||||
-- what_you_get_sprite_buttons = {['item/fast-loader'] = 1},
|
||||
-- base_cost = {fuel = 500},
|
||||
-- },
|
||||
uranium_ore = {
|
||||
tooltip = '10 green rocks of unknown origin.',
|
||||
what_you_get_sprite_buttons = {['item/uranium-238'] = 10},
|
||||
base_cost = {coins = 1000, fuel = 100},
|
||||
},
|
||||
extra_time = {
|
||||
tooltip = 'Relax at sea for an extra minute. (Increases the next destination\'s loading time.)',
|
||||
what_you_get_sprite_buttons = {['utility/time_editor_icon'] = 60},
|
||||
base_cost = {coins = 10, fuel = 1},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Public.initialise_captains_shop()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
memory.mainshop_availability_bools = {
|
||||
uranium_ore = true,
|
||||
rail_signal = true,
|
||||
artillery_shell = true,
|
||||
artillery_remote = false, --good way to get trolled by crew and remove skill
|
||||
extra_time = true,
|
||||
new_boat_sloop_with_hold = false,
|
||||
new_boat_cutter_with_hold = false,
|
||||
new_boat_cutter = false,
|
||||
buy_iron = false,
|
||||
repair_cannons = false,
|
||||
-- sell_iron = false,
|
||||
-- buy_fast_loader = true,
|
||||
-- sell_copper = false,
|
||||
}
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_fuel_gui'], {})
|
||||
end
|
||||
|
||||
function Public.main_shop_try_purchase(player, purchase_name)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local shop_data_1 = Public.main_shop_data_1
|
||||
local shop_data_2 = Public.main_shop_data_2
|
||||
local trade_data = shop_data_1[purchase_name] or shop_data_2[purchase_name]
|
||||
if not trade_data then return end
|
||||
|
||||
local stored_fuel = memory.stored_fuel
|
||||
if not stored_fuel then return end
|
||||
-- local captain_index = memory.playerindex_captain
|
||||
-- if not (stored_fuel and captain_index) then return end
|
||||
-- local captain = game.players[captain_index]
|
||||
if not Common.validate_player_and_character(player) then return end
|
||||
|
||||
local inv = player.get_inventory(defines.inventory.character_main)
|
||||
if not (inv and inv.valid) then return end
|
||||
|
||||
local multiplier = Balance.main_shop_cost_multiplier()
|
||||
|
||||
-- local rate_limit_ok = not (memory.mainshop_rate_limit_ticker and memory.mainshop_rate_limit_ticker > 0)
|
||||
local rate_limit_ok = true
|
||||
local enough_fuel = true
|
||||
local enough_iron_plates = true
|
||||
local enough_coins = true
|
||||
local enough_copper_plates = true
|
||||
local coins_got
|
||||
local iron_plates_got
|
||||
local copper_plates_got
|
||||
-- local able_to_buy_boats = memory.boat.state == Boats.enum_state.DOCKED --disabled for now
|
||||
local able_to_buy_boats = false
|
||||
-- local able_to_buy_boats = (memory.boat.state == Boats.enum_state.DOCKED or memory.boat.state == Boats.enum_state.APPROACHING) --problem with this if you buy whilst approaching, the original one no longer moves
|
||||
|
||||
for k, v in pairs(trade_data.base_cost) do
|
||||
if k == 'fuel' then
|
||||
enough_fuel = (stored_fuel >= v * multiplier)
|
||||
elseif k == 'coins' then
|
||||
coins_got = inv.get_item_count('coin')
|
||||
enough_coins = coins_got >= v * multiplier
|
||||
elseif k == 'iron_plates' then
|
||||
iron_plates_got = inv.get_item_count('iron-plate')
|
||||
enough_iron_plates = iron_plates_got >= v * multiplier
|
||||
elseif k == 'copper_plates' then
|
||||
copper_plates_got = inv.get_item_count('copper-plate')
|
||||
enough_copper_plates = copper_plates_got >= v * multiplier
|
||||
end
|
||||
end
|
||||
|
||||
local can_buy = rate_limit_ok and enough_coins and enough_fuel and enough_iron_plates and enough_copper_plates
|
||||
|
||||
if purchase_name == 'new_boat_sloop_with_hold' or purchase_name == 'new_boat_cutter_with_hold' or purchase_name == 'new_boat_cutter' then can_buy = can_buy and able_to_buy_boats end
|
||||
|
||||
-- @TODO: prevent people from buying things whilst marooned
|
||||
|
||||
if can_buy then
|
||||
for k, v in pairs(trade_data.base_cost) do
|
||||
if k == 'fuel' then
|
||||
memory.stored_fuel = memory.stored_fuel - v * multiplier
|
||||
elseif k == 'coins' then
|
||||
inv.remove{name="coin", count=v * multiplier}
|
||||
elseif k == 'iron_plates' then
|
||||
inv.remove{name="iron-plate", count=v * multiplier}
|
||||
elseif k == 'copper_plates' then
|
||||
inv.remove{name="copper-plate", count=v * multiplier}
|
||||
end
|
||||
end
|
||||
|
||||
local force = memory.force
|
||||
if not (force and force.valid) then return end
|
||||
|
||||
local gotamount
|
||||
if purchase_name == 'uranium_ore' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/uranium-238']
|
||||
Common.give(player, {{name = 'uranium-238', count = gotamount}})
|
||||
Common.notify_force_light(force,string.format('%s is buying green rocks...', player.name))
|
||||
|
||||
elseif purchase_name == 'extra_time' then
|
||||
local success = Crew.try_add_extra_time_at_sea(60 * 60)
|
||||
if success then
|
||||
Common.notify_force_light(force,string.format('%s is buying extra time at sea...', player.name))
|
||||
else
|
||||
Common.notify_player_error(player, string.format('Purchase error: Can\'t buy more time than this.', player.name))
|
||||
-- refund:
|
||||
memory.stored_fuel = memory.stored_fuel + trade_data.base_cost.fuel * multiplier
|
||||
end
|
||||
|
||||
elseif purchase_name == 'rail_signal' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/rail-signal']
|
||||
Common.give(player, {{name = 'rail-signal', count = gotamount}})
|
||||
Common.notify_force_light(force,string.format('%s is buying signals...', player.name))
|
||||
|
||||
elseif purchase_name == 'artillery_shell' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/artillery-shell']
|
||||
Common.give(player, {{name = 'artillery-shell', count = gotamount}})
|
||||
Common.notify_force_light(force,string.format('%s is buying cannon shells...', player.name))
|
||||
|
||||
elseif purchase_name == 'artillery_remote' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/artillery-targeting-remote']
|
||||
Common.give(player, {{name = 'artillery-targeting-remote', count = gotamount}})
|
||||
Common.notify_force_light(force,string.format('%s is buying an artillery targeting remote...', player.name))
|
||||
|
||||
elseif purchase_name == 'new_boat_cutter' or purchase_name == 'new_boat_cutter_with_hold' or purchase_name == 'new_boat_sloop_with_hold' then
|
||||
Dock.execute_boat_purchase()
|
||||
Common.notify_force(force,string.format('[font=heading-1]%s bought a %s.[/font]', player.name, Boats[Common.current_destination().static_params.boat_for_sale_type].Data.display_name))
|
||||
|
||||
elseif purchase_name == 'repair_cannons' then
|
||||
-- heal all cannons:
|
||||
local cannons = game.surfaces[destination.surface_name].find_entities_filtered({type = 'artillery-turret'})
|
||||
for _, c in pairs(cannons) do
|
||||
c.health = c.prototype.max_health
|
||||
end
|
||||
Common.notify_force(force,string.format('[font=heading-1]%s repaired the cannons.[/font]', player.name))
|
||||
memory.mainshop_availability_bools[purchase_name] = false
|
||||
|
||||
elseif purchase_name == Upgrades.enum.MORE_POWER then
|
||||
Upgrades.execute_upgade(Upgrades.enum.MORE_POWER)
|
||||
Common.notify_force(force,string.format('[font=heading-1]%s upgraded the ship\'s power.[/font]', player.name))
|
||||
memory.mainshop_availability_bools[purchase_name] = false
|
||||
|
||||
elseif purchase_name == Upgrades.enum.EXTRA_HOLD then
|
||||
Upgrades.execute_upgade(Upgrades.enum.EXTRA_HOLD)
|
||||
Common.notify_force(force,string.format('[font=heading-1]%s upgraded the ship\'s hold.[/font]', player.name))
|
||||
memory.mainshop_availability_bools[purchase_name] = false
|
||||
|
||||
elseif purchase_name == Upgrades.enum.UNLOCK_MERCHANTS then
|
||||
Upgrades.execute_upgade(Upgrades.enum.UNLOCK_MERCHANTS)
|
||||
Common.notify_force(force,string.format('[font=heading-1]%s unlocked merchant ships.[/font]', player.name))
|
||||
memory.mainshop_availability_bools[purchase_name] = false
|
||||
|
||||
elseif purchase_name == Upgrades.enum.ROCKETS_FOR_SALE then
|
||||
Upgrades.execute_upgade(Upgrades.enum.ROCKETS_FOR_SALE)
|
||||
Common.notify_force(force,string.format('[font=heading-1]%s unlocked the sale of rockets at covered-up markets.[/font]', player.name))
|
||||
memory.mainshop_availability_bools[purchase_name] = false
|
||||
|
||||
elseif purchase_name == 'sell_iron' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/coal']
|
||||
Common.give(player, {{name = 'fuel', count = gotamount}})
|
||||
Common.notify_force_light(force,string.format('%s is selling iron...', player.name))
|
||||
|
||||
elseif purchase_name == 'buy_iron' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/iron-plate']
|
||||
Common.give_items_to_crew{{name = 'iron-plate', count = gotamount}}
|
||||
Common.notify_force_light(force,string.format('%s is buying iron...', player.name))
|
||||
|
||||
elseif purchase_name == 'buy_copper' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/copper-plate']
|
||||
Common.give_items_to_crew{{name = 'copper-plate', count = gotamount}}
|
||||
Common.notify_force_light(force,string.format('%s is buying copper...', player.name))
|
||||
|
||||
-- elseif name == 'buy_fast_loader' then
|
||||
-- gotamount = trade_data.what_you_get_sprite_buttons['item/fast-loader']
|
||||
-- Common.give(player, {{name = 'fast-loader', count = gotamount}})
|
||||
-- Common.notify_force_light(force,string.format('%s bought a fast loader...', player.name))
|
||||
|
||||
elseif purchase_name == 'sell_copper' then
|
||||
gotamount = trade_data.what_you_get_sprite_buttons['item/coal']
|
||||
Common.give(player, {{name = 'fuel', count = gotamount}})
|
||||
Common.notify_force_light(force,string.format('%s is selling copper...', player.name))
|
||||
|
||||
end
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_fuel_gui'], {})
|
||||
|
||||
-- memory.mainshop_rate_limit_ticker = Common.mainshop_rate_limit_ticks
|
||||
else
|
||||
-- play sound?
|
||||
if rate_limit_ok == false then
|
||||
Common.notify_player_error(player, 'Purchase error: Shop rate limit exceeded.')
|
||||
end
|
||||
if enough_fuel == false then
|
||||
Common.notify_player_error(player, 'Purchase error: Not enough stored fuel.')
|
||||
end
|
||||
if enough_coins == false then
|
||||
Common.notify_player_error(player, 'Purchase error: Not enough doubloons.')
|
||||
end
|
||||
if enough_iron_plates == false then
|
||||
Common.notify_player_error(player, 'Purchase error: Not enough iron plates.')
|
||||
end
|
||||
if enough_copper_plates == false then
|
||||
Common.notify_player_error(player, 'Purchase error: Not enough copper plates.')
|
||||
end
|
||||
|
||||
if (purchase_name == 'new_boat_cutter' or purchase_name == 'new_boat_sloop_with_hold' or purchase_name == 'new_boat_cutter_with_hold') and (not able_to_buy_boats) then
|
||||
Common.notify_player_error(player, 'Purchase error: Not able to purchase ships right now.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
99
maps/pirates/shop/covered.lua
Normal file
99
maps/pirates/shop/covered.lua
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
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 Boats = require 'maps.pirates.structures.boats.boats'
|
||||
-- local Dock = require 'maps.pirates.surfaces.dock'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
-- local Upgrades = require 'maps.pirates.boat_upgrades'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local enum = {
|
||||
TIME = 'Time',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
|
||||
|
||||
Public.offers_loaders = {
|
||||
{price = {{'coin', 1500}}, offer = {type = 'give-item', item = 'loader', count = 1}},
|
||||
{price = {{'coin', 2500}}, offer = {type = 'give-item', item = 'fast-loader', count = 1}},
|
||||
{price = {{'coin', 3500}}, offer = {type = 'give-item', item = 'express-loader', count = 1}},
|
||||
}
|
||||
|
||||
Public.offers_rockets = {
|
||||
{price = {{'coin', 200}, {'electronic-circuit', 80}}, offer = {type = 'give-item', item = 'rocket-launcher', count = 1}},
|
||||
{price = {{'coin', 1000}, {'explosives', 20}, {'electronic-circuit', 20}}, offer = {type = 'give-item', item = 'rocket', count = 20}},
|
||||
}
|
||||
|
||||
Public.offers_default = {
|
||||
{price = {{'coin', 600}}, offer = {type = 'give-item', item = 'copper-plate', count = 150}},
|
||||
{price = {{'coin', 600}}, offer = {type = 'give-item', item = 'iron-plate', count = 150}},
|
||||
{price = {{'coin', 450}}, offer = {type = 'give-item', item = 'piercing-rounds-magazine', count = 14}},
|
||||
{price = {{'coin', 700}}, offer = {type = 'give-item', item = 'heavy-armor', count = 1}},
|
||||
{price = {{'coin', 400}}, offer = {type = 'give-item', item = 'grenade', count = 10}},
|
||||
{price = {{'coin', 300}}, offer = {type = 'give-item', item = 'defender-capsule', count = 3}},
|
||||
{price = {{'coin', 400}}, offer = {type = 'give-item', item = 'distractor-capsule', count = 3}},
|
||||
{price = {{'coin', 500}}, offer = {type = 'give-item', item = 'slowdown-capsule', count = 5}},
|
||||
{price = {{'coin', 500}}, offer = {type = 'give-item', item = 'poison-capsule', count = 5}},
|
||||
{price = {{'coin', 500}}, offer = {type = 'give-item', item = 'gate', count = 10}},
|
||||
{price = {{'coin', 100}}, offer = {type = 'give-item', item = 'storage-tank', count = 4}},
|
||||
{price = {{'coin', 200}}, offer = {type = 'give-item', item = 'big-electric-pole', count = 8}},
|
||||
{price = {{'coin', 200}}, offer = {type = 'give-item', item = 'steel-furnace', count = 4}},
|
||||
{price = {{'coin', 300}}, offer = {type = 'give-item', item = 'stack-inserter', count = 3}},
|
||||
{price = {{'coin', 750}}, offer = {type = 'give-item', item = 'piercing-shotgun-shell', count = 9}},
|
||||
{price = {{'coin', 800}}, offer = {type = 'give-item', item = 'flamethrower', count = 1}},
|
||||
{price = {{'coin', 1500}}, offer = {type = 'give-item', item = 'flamethrower-ammo', count = 4}},
|
||||
{price = {{'coin', 1500}}, offer = {type = 'give-item', item = 'flying-robot-frame', count = 1}},
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Public.market_generate_coin_offers(how_many)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local ret = {}
|
||||
local offerscopy = Utils.deepcopy(Public.offers_default)
|
||||
local loaderoffers = Public.offers_loaders
|
||||
|
||||
local game_completion_progress = Common.game_completion_progress()
|
||||
|
||||
if game_completion_progress < 0.2 then
|
||||
ret[#ret + 1] = loaderoffers[1]
|
||||
elseif game_completion_progress < 0.6 then
|
||||
ret[#ret + 1] = loaderoffers[2]
|
||||
else
|
||||
ret[#ret + 1] = loaderoffers[3]
|
||||
end
|
||||
|
||||
local toaddcount = how_many
|
||||
while toaddcount>0 and #offerscopy > 0 do
|
||||
local index = Math.random(#offerscopy)
|
||||
local toadd = offerscopy[index]
|
||||
ret[#ret + 1] = toadd
|
||||
for i = index, #offerscopy - 1 do
|
||||
offerscopy[i] = offerscopy[i+1]
|
||||
end
|
||||
offerscopy[#offerscopy] = nil
|
||||
toaddcount = toaddcount - 1
|
||||
end
|
||||
|
||||
if memory.rockets_for_sale then
|
||||
for _, o in ipairs(Public.offers_rockets) do
|
||||
ret[#ret + 1] = o
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
return Public
|
190
maps/pirates/shop/dock.lua
Normal file
190
maps/pirates/shop/dock.lua
Normal file
@ -0,0 +1,190 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
local Classes = require 'maps.pirates.roles.classes'
|
||||
-- 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'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
-- local Upgrades = require 'maps.pirates.boat_upgrades'
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
||||
|
||||
|
||||
Public.market_barters = {
|
||||
{price = {{'iron-plate', 300}}, offer = {type = 'give-item', item = 'copper-plate', count = 500}},
|
||||
{price = {{'copper-plate', 300}}, offer = {type = 'give-item', item = 'iron-plate', count = 500}},
|
||||
--repeating these:
|
||||
{price = {{'iron-plate', 300}}, offer = {type = 'give-item', item = 'copper-plate', count = 500}},
|
||||
{price = {{'copper-plate', 300}}, offer = {type = 'give-item', item = 'iron-plate', count = 500}},
|
||||
{price = {{'steel-plate', 40}}, offer = {type = 'give-item', item = 'copper-plate', count = 500}},
|
||||
{price = {{'steel-plate', 40}}, offer = {type = 'give-item', item = 'iron-plate', count = 500}},
|
||||
{price = {{'raw-fish', 50}}, offer = {type = 'give-item', item = 'coal', count = 500}},
|
||||
{price = {{'raw-fish', 50}}, offer = {type = 'give-item', item = 'iron-plate', count = 750}},
|
||||
{price = {{'raw-fish', 50}}, offer = {type = 'give-item', item = 'copper-plate', count = 750}},
|
||||
{price = {{'raw-fish', 50}}, offer = {type = 'give-item', item = 'steel-plate', count = 125}},
|
||||
|
||||
{price = {{'wood', 200}}, offer = {type = 'give-item', item = 'coin', count = 250}},
|
||||
--TODO: add more complex trades
|
||||
}
|
||||
|
||||
Public.market_permanent_offers = {
|
||||
{price = {{'coin', 2400}}, offer = {type = 'give-item', item = 'iron-ore', count = 800}},
|
||||
{price = {{'coin', 2400}}, offer = {type = 'give-item', item = 'copper-ore', count = 800}},
|
||||
{price = {{'coin', 3000}}, offer = {type = 'give-item', item = 'crude-oil-barrel', count = 100}},
|
||||
{price = {{'coin', 2500}}, offer = {type = 'give-item', item = 'fast-loader', count = 1}},
|
||||
{price = {{'coin', 5000}}, offer = {type = 'give-item', item = 'beacon', count = 2}},
|
||||
{price = {{'coin', 2800}}, offer = {type = 'give-item', item = 'speed-module-2', count = 2}},
|
||||
}
|
||||
|
||||
-- cheap but one-off
|
||||
Public.market_sales = {
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'coal', count = 900}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'piercing-rounds-magazine', count = 75}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'uranium-rounds-magazine', count = 30}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'piercing-shotgun-shell', count = 50}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'raw-fish', count = 300}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'laser-turret', count = 1}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'vehicle-machine-gun', count = 3}},
|
||||
{price = {{'coin', 3000}}, offer = {type = 'give-item', item = 'modular-armor', count = 1}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'distractor-capsule', count = 20}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'poison-capsule', count = 20}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'slowdown-capsule', count = 20}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'coin', count = 4000}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'roboport', count = 1}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'construction-robot', count = 10}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'logistic-chest-passive-provider', count = 2}},
|
||||
{price = {{'coin', 2000}}, offer = {type = 'give-item', item = 'logistic-robot', count = 2}},
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- function Public.dock_generate_offers(how_many_barters, how_many_sales)
|
||||
-- local ret = {}
|
||||
|
||||
-- local toaddcount
|
||||
|
||||
-- local barterscopy = Utils.deepcopy(Public.market_barters)
|
||||
-- toaddcount = how_many_barters
|
||||
-- while toaddcount>0 and #barterscopy > 0 do
|
||||
-- local index = Math.random(#barterscopy)
|
||||
-- local toadd = barterscopy[index]
|
||||
-- ret[#ret + 1] = toadd
|
||||
-- for i = index, #barterscopy - 1 do
|
||||
-- barterscopy[i] = barterscopy[i+1]
|
||||
-- end
|
||||
-- barterscopy[#barterscopy] = nil
|
||||
-- toaddcount = toaddcount - 1
|
||||
-- end
|
||||
|
||||
-- for _, offer in pairs(Public.market_permanent_offers) do
|
||||
-- ret[#ret + 1] = offer
|
||||
-- end
|
||||
|
||||
-- local salescopy = Utils.deepcopy(Public.market_sales)
|
||||
-- toaddcount = how_many_sales
|
||||
-- while toaddcount>0 and #salescopy > 0 do
|
||||
-- local index = Math.random(#salescopy)
|
||||
-- local toadd = salescopy[index]
|
||||
-- ret[#ret + 1] = toadd
|
||||
-- for i = index, #salescopy - 1 do
|
||||
-- salescopy[i] = salescopy[i+1]
|
||||
-- end
|
||||
-- salescopy[#salescopy] = nil
|
||||
-- toaddcount = toaddcount - 1
|
||||
-- end
|
||||
|
||||
|
||||
-- return ret
|
||||
-- end
|
||||
|
||||
|
||||
function Public.create_dock_markets(surface, p)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
if not (surface and p) then return end
|
||||
|
||||
local e
|
||||
|
||||
e = surface.create_entity{name = 'market', position = {x = p.x - 7, y = p.y}}
|
||||
if e and e.valid then
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.destructible = false
|
||||
|
||||
for _, offer in pairs(Public.market_permanent_offers) do
|
||||
e.add_market_item(offer)
|
||||
end
|
||||
end
|
||||
|
||||
e = surface.create_entity{name = 'market', position = {x = p.x, y = p.y - 1}}
|
||||
if e and e.valid then
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.destructible = false
|
||||
|
||||
local toaddcount
|
||||
|
||||
local salescopy = Utils.deepcopy(Public.market_sales)
|
||||
toaddcount = 3
|
||||
while toaddcount>0 and #salescopy > 0 do
|
||||
local index = Math.random(#salescopy)
|
||||
local offer = salescopy[index]
|
||||
e.add_market_item(offer)
|
||||
for i = index, #salescopy - 1 do
|
||||
salescopy[i] = salescopy[i+1]
|
||||
end
|
||||
salescopy[#salescopy] = nil
|
||||
toaddcount = toaddcount - 1
|
||||
end
|
||||
|
||||
-- new class offerings:
|
||||
local destination = Common.current_destination()
|
||||
if destination.static_params.class_for_sale then
|
||||
e.add_market_item{price={{'coin', Balance.class_cost()}}, offer={type="nothing"}}
|
||||
|
||||
destination.dynamic_data.market_class_offer_rendering = rendering.draw_text{
|
||||
text = 'Class available: ' .. Classes.display_form[destination.static_params.class_for_sale],
|
||||
surface = surface,
|
||||
target = Utils.psum{e.position, {x = 0, y = -4}},
|
||||
color = CoreData.colors.renderingtext_green,
|
||||
scale = 2.5,
|
||||
font = 'default-game',
|
||||
alignment = 'center'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
e = surface.create_entity{name = 'market', position = {x = p.x + 7, y = p.y}}
|
||||
if e and e.valid then
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.destructible = false
|
||||
|
||||
local toaddcount
|
||||
|
||||
local barterscopy = Utils.deepcopy(Public.market_barters)
|
||||
toaddcount = 2
|
||||
while toaddcount>0 and #barterscopy>0 do
|
||||
local index = Math.random(#barterscopy)
|
||||
local offer = barterscopy[index]
|
||||
e.add_market_item(offer)
|
||||
for i = index, #barterscopy - 1 do
|
||||
barterscopy[i] = barterscopy[i+1]
|
||||
end
|
||||
barterscopy[#barterscopy] = nil
|
||||
toaddcount = toaddcount - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
60
maps/pirates/shop/merchants.lua
Normal file
60
maps/pirates/shop/merchants.lua
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Roles = require 'maps.pirates.roles.roles'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Loot = require 'maps.pirates.loot'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
-- local Hold = require 'maps.pirates.surfaces.hold'
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
||||
function Public.generate_merchant_trades(market)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
if market and market.valid then
|
||||
|
||||
local game_completion_progress = Common.game_completion_progress()
|
||||
if game_completion_progress <= 1 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', 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}}
|
||||
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}}
|
||||
market.add_market_item{price = {{'coin', 8000}, {'raw-fish', 10}}, offer = {type = 'give-item', item = 'battery-mk2-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', 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', 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', count = 1}}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
201
maps/pirates/shop/shop.lua
Normal file
201
maps/pirates/shop/shop.lua
Normal file
@ -0,0 +1,201 @@
|
||||
|
||||
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 Boats = require 'maps.pirates.structures.boats.boats'
|
||||
-- local Dock = require 'maps.pirates.surfaces.dock'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
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 Public = {}
|
||||
Public.Captains = require 'maps.pirates.shop.captains'
|
||||
Public.Covered = require 'maps.pirates.shop.covered'
|
||||
Public.Merchants = require 'maps.pirates.shop.merchants'
|
||||
Public.Minimarket = require 'maps.pirates.shop.dock'
|
||||
|
||||
|
||||
|
||||
function Public.event_on_market_item_purchased(event)
|
||||
local player_index, market, offer_index, trade_count = event.player_index, event.market, event.offer_index, event.count
|
||||
local player = game.players[player_index]
|
||||
if not (market and market.valid and offer_index and Common.validate_player(player)) then return end
|
||||
|
||||
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
local alloffers = market.get_market_items()
|
||||
local this_offer = alloffers[offer_index]
|
||||
local price = this_offer.price
|
||||
local offer_type = this_offer.offer.type
|
||||
local offer_giveitem_name, offer_giveitem_count
|
||||
if offer_type == 'give-item' then
|
||||
offer_giveitem_name = this_offer.offer.item
|
||||
offer_giveitem_count = this_offer.offer.count
|
||||
end
|
||||
|
||||
local inv = player.get_inventory(defines.inventory.character_main)
|
||||
|
||||
|
||||
-- check for BARTER vs STATIC vs ONE-OFF
|
||||
-- One-off becomes unavailable after purchase, such as class purchase
|
||||
-- Static doesn't decay
|
||||
-- Barter decays
|
||||
local decay_type
|
||||
local dock_bool = destination.type == SurfacesCommon.enum.DOCK
|
||||
local island_bool = destination.type == SurfacesCommon.enum.ISLAND
|
||||
local purchase_bool = (price and price[1] and price[1].name and (price[1].name == 'coin'))
|
||||
local simple_efficiency_trade_bool = (price and price[1] and price[1].name and (price[1].name == 'pistol' or price[1].name == 'burner-mining-drill'))
|
||||
local special_purchase_bool = (offer_giveitem_name == 'rocket-launcher')
|
||||
-- local special_purchase_bool = (offer_giveitem_name and (offer_giveitem_name == 'loader' or offer_giveitem_name == 'fast-loader' or offer_giveitem_name == 'express-loader' or offer_giveitem_name == 'rocket-launcher'))
|
||||
|
||||
if offer_type == 'nothing' then
|
||||
decay_type = 'one-off'
|
||||
elseif dock_bool and purchase_bool and (offer_giveitem_name) and (offer_giveitem_name == 'stone' or offer_giveitem_name == 'iron-ore' or offer_giveitem_name == 'copper-ore' or offer_giveitem_name == 'crude-oil-barrel') then
|
||||
decay_type = 'fast_decay'
|
||||
elseif dock_bool and purchase_bool and (offer_giveitem_name) then
|
||||
decay_type = 'one-off'
|
||||
elseif simple_efficiency_trade_bool or special_purchase_bool then
|
||||
decay_type = 'static'
|
||||
elseif island_bool and (not (offer_giveitem_name and offer_giveitem_name == 'rocket')) then
|
||||
decay_type = 'one-off'
|
||||
else
|
||||
decay_type = 'decay'
|
||||
end
|
||||
|
||||
-- For everything but static, we want to disallow multi-purchases in this game, so refund any additional purchases:
|
||||
if decay_type ~= 'static' and player and trade_count and trade_count > 1 then
|
||||
inv = player.get_inventory(defines.inventory.character_main)
|
||||
if not inv then return end
|
||||
for _, p in pairs(price) do
|
||||
inv.insert{name = p.name, count = p.amount * (trade_count - 1)}
|
||||
end
|
||||
if offer_type == 'give-item' then
|
||||
inv.remove{name = offer_giveitem_name, count = offer_giveitem_count * (trade_count - 1)}
|
||||
end
|
||||
end
|
||||
|
||||
if decay_type == 'one-off' then
|
||||
local force = player.force
|
||||
|
||||
if offer_type == 'nothing' and destination.static_params.class_for_sale then
|
||||
|
||||
local class_for_sale = destination.static_params.class_for_sale
|
||||
-- if not class_for_sale then return end
|
||||
local required_class = Classes.class_purchase_requirement[class_for_sale]
|
||||
|
||||
local ok = true
|
||||
-- check if they have the required class to buy it
|
||||
if required_class then
|
||||
if not (memory.classes_table and memory.classes_table[player.index] and memory.classes_table[player.index] == required_class) then
|
||||
ok = false
|
||||
Common.notify_force_error(force, string.format('Class purchase error: You need to be a %s to buy this.', Classes.display_form[required_class]))
|
||||
end
|
||||
end
|
||||
|
||||
if ok then
|
||||
if required_class then
|
||||
if force and force.valid then
|
||||
Common.notify_force_light(force,string.format('%s upgraded their class from %s to %s. ([font=scenario-message-dialog]%s[/font])', player.name, Classes.display_form[required_class], Classes.display_form[class_for_sale], Classes.explanation[class_for_sale]))
|
||||
end
|
||||
else
|
||||
-- check if they have a role already - renounce it if so
|
||||
if memory.classes_table and memory.classes_table[player.index] then
|
||||
Classes.try_renounce_class(player, false)
|
||||
end
|
||||
|
||||
if force and force.valid then
|
||||
Common.notify_force_light(force,string.format('%s bought the class %s. ([font=scenario-message-dialog]%s[/font])', player.name, Classes.display_form[class_for_sale], Classes.explanation[class_for_sale]))
|
||||
end
|
||||
end
|
||||
|
||||
memory.classes_table[player.index] = class_for_sale
|
||||
|
||||
memory.available_classes_pool = Utils.ordered_table_with_single_value_removed(memory.available_classes_pool, class_for_sale)
|
||||
|
||||
if destination.dynamic_data and destination.dynamic_data.market_class_offer_rendering then
|
||||
rendering.destroy(destination.dynamic_data.market_class_offer_rendering)
|
||||
end
|
||||
|
||||
market.remove_market_item(offer_index)
|
||||
|
||||
if Classes.class_unlocks[class_for_sale] then
|
||||
for _, upgrade in pairs(Classes.class_unlocks[class_for_sale]) do
|
||||
memory.available_classes_pool[#memory.available_classes_pool + 1] = upgrade
|
||||
end
|
||||
end
|
||||
else
|
||||
--refund
|
||||
inv = player.get_inventory(defines.inventory.character_main)
|
||||
if not inv then return end
|
||||
for _, p in pairs(price) do
|
||||
inv.insert{name = p.name, count = p.amount}
|
||||
end
|
||||
end
|
||||
else
|
||||
Common.notify_force_light(player.force, player.name .. ' bought ' .. this_offer.offer.count .. ' ' .. this_offer.offer.item .. ' for ' .. price[1].amount .. ' ' .. price[1].name .. '.')
|
||||
|
||||
market.remove_market_item(offer_index)
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
-- print:
|
||||
if (price and price[1]) then
|
||||
if not (price[1].name and price[1].name == 'burner-mining-drill') then --this one is too boring to announce
|
||||
if price[2] then
|
||||
local fish = price[2].name
|
||||
if fish == 'raw-fish' then fish = 'fish' end
|
||||
Common.notify_force_light(player.force, player.name .. ' traded away ' .. price[1].amount .. ' ' .. price[1].name .. ' and ' .. fish .. ' for ' .. this_offer.offer.count .. ' ' .. this_offer.offer.item .. '.')
|
||||
else
|
||||
if price[1].name == 'coin' then
|
||||
Common.notify_force_light(player.force, player.name .. ' bought ' ..this_offer.offer.count .. ' ' .. this_offer.offer.item .. ' for ' .. price[1].amount .. ' ' .. price[1].name .. '.')
|
||||
elseif this_offer.offer.item == 'coin' then
|
||||
local sold_amount = price[1].amount
|
||||
if sold_amount == 1 then sold_amount = 'a' end
|
||||
Common.notify_force_light(player.force, player.name .. ' sold ' .. sold_amount .. ' ' .. price[1].name .. ' for ' .. this_offer.offer.count .. ' ' .. this_offer.offer.item .. '.')
|
||||
else
|
||||
Common.notify_force_light(player.force, player.name .. ' traded away ' .. price[1].amount .. ' ' .. price[1].name .. ' for ' .. this_offer.offer.count .. ' ' .. this_offer.offer.item .. '.')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if decay_type == 'static' then
|
||||
if not inv then return end
|
||||
local flying_text_color = {r = 255, g = 255, b = 255}
|
||||
local text1 = '[color=1,1,1]+' .. this_offer.offer.count .. '[/color] [item=' .. alloffers[offer_index].offer.item .. ']'
|
||||
local text2 = '[color=' .. flying_text_color.r .. ',' .. flying_text_color.g .. ',' .. flying_text_color.b .. '](' .. inv.get_item_count(alloffers[offer_index].offer.item) .. ')[/color]'
|
||||
|
||||
Common.flying_text(player.surface, player.position, text1 .. ' [font=count-font]' .. text2 .. '[/font]')
|
||||
else
|
||||
local decay_param = Balance.barter_decay_parameter()
|
||||
if decay_type == 'fast_decay' then decay_param = Balance.barter_decay_parameter()^3 end
|
||||
|
||||
if not inv then return end
|
||||
local flying_text_color = {r = 255, g = 255, b = 255}
|
||||
local text1 = '[color=1,1,1]+' .. this_offer.offer.count .. '[/color] [item=' .. alloffers[offer_index].offer.item .. ']'
|
||||
local text2 = '[color=' .. flying_text_color.r .. ',' .. flying_text_color.g .. ',' .. flying_text_color.b .. '](' .. inv.get_item_count(this_offer.offer.item) .. ')[/color]'
|
||||
|
||||
Common.flying_text(player.surface, player.position, text1 .. ' [font=count-font]' .. text2 .. '[/font]')
|
||||
|
||||
--update market trades:
|
||||
alloffers[offer_index].offer.count = Math.max(Math.floor(alloffers[offer_index].offer.count * decay_param),1)
|
||||
|
||||
market.clear_market_items()
|
||||
for _, offer in pairs(alloffers) do
|
||||
market.add_market_item(offer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
1344
maps/pirates/structures/boats/boats.lua
Normal file
1344
maps/pirates/structures/boats/boats.lua
Normal file
File diff suppressed because it is too large
Load Diff
27
maps/pirates/structures/boats/merchant_1/data.lua
Normal file
27
maps/pirates/structures/boats/merchant_1/data.lua
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_name = 'merchant_1'
|
||||
Public.tile_areas = {
|
||||
{{-30,-6},{-5,5}},
|
||||
{{-5,-5},{-4,4}},
|
||||
{{-4,-4},{-3,3}},
|
||||
{{-3,-3},{-2,2}},
|
||||
{{-2,-2},{-1,1}},
|
||||
{{-1,-1},{0,0}},
|
||||
}
|
||||
Public.width = 30
|
||||
Public.height = 11
|
||||
Public.entities = {
|
||||
static = {
|
||||
pos = { x = -17, y = -0.5},
|
||||
bp_str = [[0eNqdmd1uozAUhN/F16TCNrYhr7KqVvmxskgEIkK2G1V594W0aquGwWd6iQpfx0dzju3Jq9o2l3jq63ZQ61d1bjen1dCtDn29n57/qbVxmbqqtda3TNW7rj2r9a/xxfrQbprpleF6imqt6iEeVabazXF6eum6fWxXuz/xPKjpw3YfR5a+PWcqtkM91PGNc3+4/m4vx23sxxfmCZk6defxo659F6Wf3lU9udste8CYD8y2PqxiE3dDX+9Wp66JjyxzJ9lRZRvrw59td+knbVVmTOb98wzeClXmyyoLEmPmMU6IsctqvBBjljFBiHHLmFKIKZYx1QfmfNw0TcoK7kulv9nBZLqc84LOhUrDslIttb5PcIyQUyU4UpOXCY7U5TrR01rqc51oOy11uk50jJZ6XSd6RpecTT94Mz6dxtasTyt21WDcGKnhdaLFjXjYJ5rcUONeu/l5PzV4Fuxc7cxnL5yHGBsoNCRKJ+6FxLAw4l5ITAvjv6ysa+PqZbTfAgYtLAgLVCU4pZBTJjhisyemoBWbPTEGrdTsJjEGrXS+m8QYtNIBbxJj0EpdbRJj0EpdbRIDwXryZGUBJ5CcAnBKdvYiQZWsXd2yniKXYYoERnPDA2EMhwG1KT79vOmHumlif10Nl76PC4dYf99A93U/bhn3v/o5MntQd0ChIzkecDx55ER6AslBekryyIn0VCQH6HE5eXRFHE1ywLqcEe5qLsGxJAetqxByioQeR3KQHi/k+IQedlwHwClJTgk4FdlfQI/Pyb5AHNbPiGO4XQiUx1tuF0IY1s1oVY7bhpAcz2dPOn+8jPgKXEY86/IKCGVdPt2rZ0E/DFnuvG/rHqsX8rlVh/yHV+TZ/4JqGzR7UAPFDYbOGEB1g/3B5fbRUGP9xtrORwOhIK+3UCvZQqh45KUUyglsmowyTbpVEKhis1oUj+ZsWotAms1rEciwiS0CWTZQRaCCTVQRyLGRKgJ5NlNFoECHqohU0qkqItEBIyJVOZ2rIpKms0pEMnRYiUiWDgERqaBTQERydF6GSJ4OzBAp0IkZIpV0ZIZIFZ2Zocg/z+nUDKI0nZvdUc/Z26+26y+/AWfqb+zP909MqYtQmVBYX1SmvN3+A/EBuBE=]],
|
||||
},}
|
||||
Public.market_pos = {x = -8.5, y = 0.5}
|
||||
|
||||
Public.landingtrack = {
|
||||
offset = {x = -24, y = -10.5},
|
||||
bp = [[0eNqV3M1u20YYRuF74VoB8g7J+dGtFFm4tpAKcCTDVn+CwPdeu2aLblrwWQo4psg5M5vz0fox/fz46+np+Xy5Tccf08vl7unT7frp6/P54f3zH9NxLofp+3QseT1M5/vr5WU6/vQGnr9e7h7fkdv3p9N0nM6307fpMF3uvr1/+v16fThdPt3/cnq5Te9/eHk4vV0rr18O0+38ePq4yNP15Xw7Xy/bN3180efXf67y9m33z6fb6e0K/wFH4CLwLPBC91yJbkR3ogct304zs2icReMsGmfROIvGmTTOpHEmjTNpnEnjIhoX0biIxkU0LqJxIY0LaVxI40IaF9K4isZVNK6icRWNq2hcSeNKGlfSuJLGlTRW0VhFYxWNVTRW0VhJYyWNlTRW0lhJYxONTTQ20dhEYxONjTQ20thIYyONjTR20dhFYxeNXTR20dhJYyeNnTR20thJ4xCNQzQO0ThE4xCNgzQO0jhI4yCNgzTms3jc6BBdiJ6JXuy+q+HN8G74sFXcqygkNCQ0JDQkNCQ0JjQmNCY0JjQmlNJOqO2E4k6o7oTyTqzvxAJPrPDEEk+s8YQiT6jyhDJPqPOEQk+s9MRST6z1xGJPrPaEck+o94SCT6j4hJJPrPnEok+s+sSyT6z7hMJPqPyE0k+o/YTiT6z+xPJPrP/EAlCsAIUSUKgBhSJQqAKFMlCsA8VCUKwExVJQrAWFYlCoBoVyUKgHhYJQrAjFklCsCcWiUKwKhbJQqAuFwlCoDIXS0Eav9pSIV8Ob4d3wYYr2+qf6FMpPof4UClChArXRK9HV1sRuJXYvwZtphnfDh/nf+y4FBbRCAa1QQCsU0AoFtI1eia5EN1tBe8zYc8YeNPakwUfthg/bXHt3LnXFQl2xUFcs1BULdcWNXomuRDeiu623LWFsDWOLGFvF2DLG1jG4kMN27t5jYa/p2Xt69qKevalnr+oVOkSFDlGhQ1ToEH3Qw+yYnpifmKCYoZiimKOYpJilmKbdJ5TifKE4XyjOF4rzheL8Rq9EV6Ib0Z3oYXZQptmM6Yz5jAmNGY0pjTmNSY1Z3X2gadxSaNxSaNxSaNyy0SvRlehGdCd6mB2UaTZjOmM+Y0JjRmNKY05jUncfUZpxFZpxFZpxbfRKdCW6Ed2JtvXefYpWO0WrnaLVTtFqp2i1U2QzzmIzzmIzzkKzv0Kzv41eia5EN6JtTQbRuzd6tY1ebaNX2+jVNnq1jW6z32Kz30Jjy41eia5E2313ogfRu/dis73YbC8224vN9mKzvWhj60JD0Y22azeiO9GD6N3bpdt26bZdum2XbtvF5taFBpcb3YjuRA+idxsdZnSY0WFGbfw704huozvRg+i9i/43HsOL4Xv/UZpGOhs9iN69LrF1sfHSTCF9o3ffunX3+f8i4JfDx28vHP/1Sw6H6bfT88tfFyg9SxulLXNdRumvr38Cd8bxwA==]],
|
||||
}
|
||||
|
||||
return Public
|
9
maps/pirates/structures/boats/merchant_1/merchant_1.lua
Normal file
9
maps/pirates/structures/boats/merchant_1/merchant_1.lua
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
-- local Data = require 'maps.pirates.structures.boats.merchant_1.data'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.structures.boats.merchant_1.data'
|
||||
|
||||
|
||||
|
||||
return Public
|
36
maps/pirates/structures/boats/raft/data.lua
Normal file
36
maps/pirates/structures/boats/raft/data.lua
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_name = 'raft'
|
||||
Public.capacity = 11
|
||||
Public.tile_areas = {
|
||||
{{-9,-4},{0,5}},
|
||||
}
|
||||
Public.width = 9
|
||||
Public.height = 9
|
||||
Public.spawn_point = {x = -3, y = 0}
|
||||
Public.areas_infront = {
|
||||
{{0,-4},{1,5}},
|
||||
}
|
||||
Public.areas_behind = {
|
||||
{{-10,-4},{-9,5}},
|
||||
}
|
||||
Public.areas_offright = {
|
||||
{{-9,5},{0,6}},
|
||||
}
|
||||
Public.areas_offleft = {
|
||||
{{-9,-5},{0,-4}},
|
||||
}
|
||||
Public.entities = {
|
||||
inaccessible = { --this 'left wall' stops biters from being deleted by water
|
||||
pos = { x = -8.5, y = 0},
|
||||
bp_str = [[0eNqV08sOwiAQBdB/mTU1ltIXv2KMqXZSSdqhKfhoDP9uQRcmsmF5k7mHWQwvOI83nBdFFuQLDHVzZnU2LKr3+QkyZ7CCbB0DddFkQB62MTVQN/oBu84IEpTFCRhQN/n00LpHyi5XNBZ8kXr0kjsyQLLKKvw4Iawnuk1nXMJTMYHBrM1W0vRdab8rw1L5rnSO/TE8kdnHmSKRKeKMSGR4nCkTmTLOVImMiDN1IlPHmSaRqeJMm8g0ntluMVyt/PkBDO64mFDgTS7qlteiqETLG+fekGkHZg==]],
|
||||
},
|
||||
}
|
||||
|
||||
Public.landingtrack = {
|
||||
offset = {x = 3.5, y = -7},
|
||||
bp = [[0eNqV2M1qwkAYheF7mXWE+eZ/civFhdVBBjQJSSwVyb3XVBddtMV3JYHjBJ85m+NNvZ8uZRhrN6v2pqZuN2zmfnMc62F9/lStmEZd7x9+aVTd992k2rd7sB673WmNzNehqFbVuZxVo7rdeX265/ZjmYtav9QdynrOsm3UXE/lccDQT3Wuffd8y+b5Gr38dsafcWFxA0+neQvz7tW8MBxhOMJwBOIIxBGIoxmOZjia4WiIoyGOZjgZ2WREk5FMZjCZuWTGkhBLQiwJsSTGkhhLYiwRsUTEEhFLZCyRsUTGEhBLQCwBsQTGEhhLYCwesXjE4hGLZyyesXjG4hCLQywOsTjG4hiLYywWsVjEYhHLI21Rmv1Kj9IBpSNKJ5TO7HbgZbLbFHadwu7z5dqyWcJWCRslBtXWoNoaVFuDamtQbQ2qrUG1Nay2htUWbkY4GeliZJuITSK2iFBtBdVWUG0F1VZQbQXVVlBthdVWWG3pmod79Z/abpvHv0btj/+gGvVRxun7AJPExWyiDc5pa5blC6gg570=]],
|
||||
}
|
||||
|
||||
return Public
|
9
maps/pirates/structures/boats/raft/raft.lua
Normal file
9
maps/pirates/structures/boats/raft/raft.lua
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
-- local Data = require 'maps.pirates.structures.boats.raft.data'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.structures.boats.raft.data'
|
||||
|
||||
|
||||
|
||||
return Public
|
36
maps/pirates/structures/boats/raft_large/data.lua
Normal file
36
maps/pirates/structures/boats/raft_large/data.lua
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_name = 'raft_large'
|
||||
Public.capacity = 38
|
||||
Public.tile_areas = {
|
||||
{{-18,-4},{0,5}},
|
||||
}
|
||||
Public.width = 18
|
||||
Public.height = 9
|
||||
Public.spawn_point = {x = -6, y = 0}
|
||||
Public.areas_infront = {
|
||||
{{0,-4},{1,5}},
|
||||
}
|
||||
Public.areas_behind = {
|
||||
{{-19,-4},{-18,5}},
|
||||
}
|
||||
Public.areas_offright = {
|
||||
{{-18,5},{0,6}},
|
||||
}
|
||||
Public.areas_offleft = {
|
||||
{{-18,-5},{0,-4}},
|
||||
}
|
||||
Public.entities = {
|
||||
inaccessible = { --this 'left wall' stops biters from being deleted by water
|
||||
pos = { x = -17.5, y = 0},
|
||||
bp_str = [[0eNqV08sOwiAQBdB/mTU1ltIXv2KMqXZSSdqhKfhoDP9uQRcmsmF5k7mHWQwvOI83nBdFFuQLDHVzZnU2LKr3+QkyZ7CCbB0DddFkQB62MTVQN/oBu84IEpTFCRhQN/n00LpHyi5XNBZ8kXr0kjsyQLLKKvw4Iawnuk1nXMJTMYHBrM1W0vRdab8rw1L5rnSO/TE8kdnHmSKRKeKMSGR4nCkTmTLOVImMiDN1IlPHmSaRqeJMm8g0ntluMVyt/PkBDO64mFDgTS7qlteiqETLG+fekGkHZg==]],
|
||||
},
|
||||
}
|
||||
|
||||
Public.landingtrack = {
|
||||
offset = {x = 4.5, y = -7},
|
||||
bp = [[0eNqV2M1qwkAYheF7mXWE+eZ/civFhdVBBjQJSSwVyb3XVBddtMV3JYHjBJ85m+NNvZ8uZRhrN6v2pqZuN2zmfnMc62F9/lStmEZd7x9+aVTd992k2rd7sB673WmNzNehqFbVuZxVo7rdeX265/ZjmYtav9QdynrOsm3UXE/lccDQT3Wuffd8y+b5Gr38dsafcWFxA0+neQvz7tW8MBxhOMJwBOIIxBGIoxmOZjia4WiIoyGOZjgZ2WREk5FMZjCZuWTGkhBLQiwJsSTGkhhLYiwRsUTEEhFLZCyRsUTGEhBLQCwBsQTGEhhLYCwesXjE4hGLZyyesXjG4hCLQywOsTjG4hiLYywWsVjEYhHLI21Rmv1Kj9IBpSNKJ5TO7HbgZbLbFHadwu7z5dqyWcJWCRslBtXWoNoaVFuDamtQbQ2qrUG1Nay2htUWbkY4GeliZJuITSK2iFBtBdVWUG0F1VZQbQXVVlBthdVWWG3pmod79Z/abpvHv0btj/+gGvVRxun7AJPExWyiDc5pa5blC6gg570=]],
|
||||
}
|
||||
|
||||
return Public
|
9
maps/pirates/structures/boats/raft_large/raft_large.lua
Normal file
9
maps/pirates/structures/boats/raft_large/raft_large.lua
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
-- local Data = require 'maps.pirates.structures.boats.raft_large.data'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.structures.boats.raft_large.data'
|
||||
|
||||
|
||||
|
||||
return Public
|
183
maps/pirates/structures/boats/sloop/data.lua
Normal file
183
maps/pirates/structures/boats/sloop/data.lua
Normal file
File diff suppressed because one or more lines are too long
9
maps/pirates/structures/boats/sloop/sloop.lua
Normal file
9
maps/pirates/structures/boats/sloop/sloop.lua
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
-- local Data = require 'maps.pirates.structures.boats.sloop.data'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.structures.boats.sloop.data'
|
||||
|
||||
|
||||
|
||||
return Public
|
@ -0,0 +1,19 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
MATTISSO = 'MATTISSO',
|
||||
ROC = 'ROC',
|
||||
}
|
||||
Public[enum.MATTISSO] = require 'maps.pirates.structures.island_structures.mattisso.mattisso'
|
||||
Public[enum.ROC] = require 'maps.pirates.structures.island_structures.roc.roc'
|
||||
Public.enum = enum
|
||||
|
||||
|
||||
return Public
|
334
maps/pirates/structures/island_structures/mattisso/data.lua
Normal file
334
maps/pirates/structures/island_structures/mattisso/data.lua
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,43 @@
|
||||
|
||||
local Data = require 'maps.pirates.structures.island_structures.mattisso.data'
|
||||
|
||||
local Public = {}
|
||||
Public.refuel_station = {}
|
||||
Public.refuel_station.Data = Data.refuel_station
|
||||
Public.small_crashed_ship = {}
|
||||
Public.small_crashed_ship.Data = Data.small_crashed_ship
|
||||
Public.small_basic_factory = {}
|
||||
Public.small_basic_factory.Data = Data.small_basic_factory
|
||||
Public.small_early_enemy_outpost = {}
|
||||
Public.small_early_enemy_outpost.Data = Data.small_early_enemy_outpost
|
||||
Public.small_nuclear_powerplant = {}
|
||||
Public.small_nuclear_powerplant.Data = Data.small_nuclear_powerplant
|
||||
Public.small_market_outpost = {}
|
||||
Public.small_market_outpost.Data = Data.small_market_outpost
|
||||
|
||||
-- second lot:
|
||||
Public.small_abandoned_refinery = {}
|
||||
Public.small_abandoned_refinery.Data = Data.small_abandoned_refinery
|
||||
Public.small_roboport_base = {}
|
||||
Public.small_roboport_base.Data = Data.small_roboport_base
|
||||
Public.small_solar_base = {}
|
||||
Public.small_solar_base.Data = Data.small_solar_base
|
||||
Public.small_mining_base = {}
|
||||
Public.small_mining_base.Data = Data.small_mining_base
|
||||
Public.small_primitive_mining_base = {}
|
||||
Public.small_primitive_mining_base.Data = Data.small_primitive_mining_base
|
||||
Public.small_oilrig_base = {}
|
||||
Public.small_oilrig_base.Data = Data.small_oilrig_base
|
||||
|
||||
-- third lot:
|
||||
Public.small_radioactive_lab = {}
|
||||
Public.small_radioactive_lab.Data = Data.small_radioactive_lab
|
||||
Public.small_radioactive_centrifuge = {}
|
||||
Public.small_radioactive_centrifuge.Data = Data.small_radioactive_centrifuge
|
||||
Public.small_radioactive_reactor = {}
|
||||
Public.small_radioactive_reactor.Data = Data.small_radioactive_reactor
|
||||
Public.uranium_miners = {}
|
||||
Public.uranium_miners.Data = Data.uranium_miners
|
||||
|
||||
|
||||
return Public
|
355
maps/pirates/structures/island_structures/roc/data.lua
Normal file
355
maps/pirates/structures/island_structures/roc/data.lua
Normal file
@ -0,0 +1,355 @@
|
||||
|
||||
local Public = {}
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
|
||||
Public.shelter1 = {
|
||||
name = 'shelter1',
|
||||
width = 18,
|
||||
height = 18,
|
||||
components = {
|
||||
{
|
||||
type = 'static',
|
||||
force = 'environment',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqV1t1qhDAQBeB3metYzL/6KqUUtxuWgEbRbFtZfPca24tCOyRztSskHzlh4OQBl+Hu5sWHCN0D1tDPVZyq2+Kv6fsTOm4YbOlnZ+DfprBC93ws9LfQD2lJ3GYHHfjoRmAQ+jF9rXEKrvrohwHStnB1SdpfGLgQffTuWzk/ttdwHy9uORb8t5/BPK3Hlin8HKiyT/o8Uvqz7+wPI8oYk2FkGaMyjCpjdIbRZYzMMKaIySm2SMlFaoqU3P22RUpuZnhdxORmhlNHWCOOIDoGcSTtdjBG0RgslSamkohjiI5CHEuLhTENjcFStbRUyGlETWOQ0whOCoUpgqRgkSQtEjLFQtEYZIqFJmXCFENSsEiW1nVYYza0m8GYllaZWPHWtMrEGE6rTIwRpMrEFEmqTExRpMrEFNoAY4ohNeapHO+/853Y/Xp1Mnh3y3puEA1XthVWWqt5rfb9C+jHZns=]],
|
||||
},
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = CoreData.world_concrete_tile,
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqV2t1qGkEYBuB7mWOF+Z/UWyk5sMkSFswquv0JwXtvTErpSUufoyCMa9CHj+H93tfw5fB1Op3nZQ2713BZ9qftetw+nefH2+sfYZf6Jrzc/lw3YX44Lpew+/x2cH5a9ofbkfXlNIVdmNfpOWzCsn++vbqsx2Xaft8fDuH2tuVxuj3per8J63yYPh5xOl7mdT4uvz5ne/f+Odu76++nvH3aw3lap7dn/PX4sOPdjjc7Xu14sePZjic6Hum0Pdv+cftW7Cu339Ow/K/EYc6HOR/mfJjzYc6HOR/mfJjzQc4HOR/kfJDzQc4HOR/kfJDzbs67Oe/mvJvzbs67Oe/mvJvzTs47Oe/kvJPzTs47Oe/kvJPzZs6bOW/mvJnzZs6bOW/mvJnzRs4bOW/kvJHzRs4bOW/kvJHzas6rOa/mvJrzas6rOa/mvJrzSs4rOa/kvJLzSs4rOa/kvJLzYs6LOS/mvJjzYs6LOS/mvJjzQs4LOS/kvJDzQs4LOS/kvJDzbM6zOc/mPJvzbM6zOc/mPJvzTM4zOc/kPJPzTM4zOc/kPJPzZM6TOU/mPJnzZM6TOU/mPJnzRM4TOU/kPJHzRM4TOU/kPInzSMwjKY+EPJLxSMQjCY8EPJLvKLyj6I6CO4rtKLSjyI4CO4prG982vW142+y20W2T2wa3zW0a2zS1aWjTzKaRTRObBjbNa7t+2+3bLt9297art9287eJt9266dtOtmy7ddOemKzfduOnCTfdti08sPbHwxLITi04sObHgxHITik0oNaHQhDITikwoMaHAhPISi78t/bbw27Jvi74t+bbg23Jvir0p9abQmzJvirwp8abAm/JuW1/a9tKWl7a7tNWlbS5tcWl7S1pb0taSlpa0s6SVJW0saWFJ+0qrn1j7xMon1j2x6ok1T6x4Yr0Tqp1Q64RKJ9Q5ocoJNU6ocEJ9E6sPWnvQyoPWHbTqoDUHrThovUGqDVJrkEqD1BmkyiA1Bqkw+I++4P3mozG++6N/vgnfpvPl/e35LtXxKY8yRkuxXq8/AdUS1bk=]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.shelter2 = {
|
||||
name = 'shelter2',
|
||||
width = 44,
|
||||
height = 44,
|
||||
components = {
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = 'red-desert-2',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqd3dFu4zYahuF78XEC+JVkSZxbWfRg2hqFgUwSJOnuFkXufZPW07Mu/PSomIL0aERJPwjye/j74ceHX8/PL5fHt8OX3w+vj1+f79+e7n95ufz8+ef/Hr4s093ht8//vN8dLj89Pb4evvzro+Hll8evD59N3n57Ph++HC5v52+Hu8Pj12+ff3p9e3o83//n68PD4bPb48/nj1/q/Ye7w9vl4fznTzw/vV7eLk+P17/nfuqPv+j+9P7Xz3z8dT+9nN/OHz/y9+0XbD9j+wnbZ+2P1hx/HS8e783Nt/74563Zsf2G7Vdsf8L2+u+dsf2E7bP2R2uOv44Xj/cGbz2OLD44tz6Xjes4HbHDwPY7ttd/wIrtT9h+wfYztp90wKw9Di/+Ol483hu89Tiy+ODgc4mP/c1v1X59CibtkHY4Ygf9J+zYfsP2K7Y/YfsF28/YnkfY2uPw4q/jxeO9wVuPI4sPDj6X+NjjW6Vv7e2fhe36lM3aYdIOfElH7DCw/Y7tN2y/YvsTtl+wvQ4xj7C1x+HFX8eLx3uDtx5HFh8cfC7xsce3St9a/Szc/t1Zr0/loh1m7cCXlHY4YoeB7Xdsv2H7FdufsL2OsQ4xj7C1x+HFX8eLx3uDtx5HFh8cfC7xsce3St9a/Szod+f2D9vp+hSftMOiHfiSJu2Qdjhih4Htd2y/YfsV2+sg6xjrEPMIW3scXvx1vHi8N3jrcWTxwcHnEh97fKv0rdXPgn539MN2+5dzuT71q3Y4aQe+pFk7TNoh7XDEDgPb79h+w/Y6yjrIOsY6xDzC1h6HF38dLx7vDd56HFl8cPC5xMce3yp9a/WzoN8d/bDpl/P2T/N8fUs27bBqB76kRTvM2mHSDmmHI3YY2H7H9jrMOso6yDrGOsQ8wtYehxd/HS8e7w3eehxZfHDwucTHHt8qfWv1s6DfHf2w6ZdTP823f/un61u1a4dNO/AlnbTDoh1m7TBph7TDETsMbK/jrMOso6yDrGOsQ8wjbO1xePHX8eLx3uCtx5HFBwefS3zs8a3St1Y/C/rd0Q+bfjn106zf/tuLS1q+0vKVlq+0fKXlKy1faflKy1davsLyFZavsHyF5QtjJGGMJIyRhDGSMEaSxUiyGEkWI8liJFmM5NocRxYfHHwu8bHHt0rfWv0s6HdHP2z65dRPs377by8u3xM2Qzvs2oEvadUOJ+2waIdZO0zaIe1wxA460DrOOsw6yjrIOsY6xDzC1h6HF38dLx7vDd56HFl8cPC5xMce3yp9a/WzoN8d/bDpl1M/zfrt1+Jyc/UaWB4HVseBxXFgbRxYGgdWxoGFcWBdHFgWNYiKOVSMoWIKFUOomEHFCComUDGAivlTi59a+tTCp5Y9teipJU8teGq5U4udWup0WAUcVgCH1b9h5W9Y9RtW/IbVvmGlb1jl+x4cPVr7myvljpVyx0q5Y6XcsVLuWCl3rJSazdZotiazMZiNuWyMZWMqG0PZmMnGSDYmsjGQbXlsi2NbGtvC2JbFtii2JbEtiG05bIthYwobQ9i7VcrdKuVulXK3SrlbpdytUu7/pFLeXPg2LKwbFtYNC+uGhXXDwrphYd2wsKoloJSASgIKCaAjgIwAKgKICKAhgIQACgIICKAfYHyA6QGGB5gdYHSAyQEGB5gbYGyAqQGIBqAZgGTAZoV1s8K6WWHdrLBuVlg3K6ybFdYVC+uKhXXFwrpiYV2xsK5YWJWmUJlCYQp1KZSlQJUCUQo0KZCkQJECQQr0KJCjQI3CMAqzKIyiMInCIApzKIyhMIXCEAozKJCgQIECAQr0J1YrrKsV1tUK62qFdbXCulph/U4khO2P1l6v5+Z/7gkL8QkLscIl6pYoW6JqiaIlapYgWYJiCYIl6JUgV4JaCWIlaJUgVWJSiUEl5pQYU2JKiSElZpQYUWJCiQEl6JMgT4I6CeIkaJOcrBCfrBCfrBCfrBCf/kkhvrmuLli3F6zbC9btBev2gnVbkRo1apSoUaFGgRr1aZSnQZ0GcRq0aZCmQZkGYRp0aZClQZXGUBozaYykMZHGQBrzaIyjMY3GMBqzaJCiQYkGIRp0aJChQYVmsbq9WN1erG4vVrcXq9sz1u0Z6/aMdXvGuq1ekHJBqgUpFqRWkFJBKgUpFIROEDJBqAQhEoRGEBJBKAQhEIQ+kPFApgMZDmQ2kNFAJgMZDGQukLFApgIhCoQmEJJAKAIhCIQeEHJAs9Xt2er2bHV7tro9Yd2esG5PWLdVVlJYSV0lZZVUVVJUSU0lJZVUVEJQCT0l5JRQU0JMCS0lpJRQUkJIyRwlY5RMUTJEyQwlI5RMUDJAyfwk45NQT0I8Ce0kpJNQTkI4Cd0kZJMmq9uT1e3J6nZYt8O6nRobSmyosKHAhvoaymuorqG4htoaSmugrIGwBroayGqgqoGoBpoaSGqgqGGghnkaxmmYpmGYhlkaRmmYpGGQhjkayGigooGIBhoaSGigoIGABvoZVrezuh3V7aOV7aNVbYSxkMVCFAtJLASxkMNCDAspLISwkMEyBMsILAOwjL8y/MroK4OvjL0y9IrIKwKviLsi7IqoK4KuiLki5IqIKwKujLcy3MpoK4OtjLUy1MpIKwOtjLM6Ujk+UjXGSTTOoXEKjTNonEDj/Bmnzzh7xskzzp1x6owzZ5s427zZps02a7ZJs82ZbcpsM2abMNN8mabLNFumyTLNlWmqTDNlmijTPJmmyTZLtkmyzZFtimwzZJsg2/zYpsc2O7bJsc2NcSkaV6JxIRrXoXEZGlehcREa16BxCRpXoHEBGtefbfnZVp9t8dnWnm3p2VaebeHZ1p1t2ZlWnWnRmdacacmZVpxpwZnWm2m5mVababHZ1pptqdlWmm2h2daZbZnZVpltkdnWmG2J2VaYcUM37ufG7dy4mxs3c+NebtzKjTu5cSM37uPGbdy4i9s2cdsebtvCbTu4bQO37d+27du2e9s2b9Pebdq6TTu3aeM27dumbdu0a5s2bdOebdqybTu2bcO27de27dq2W9s2a9tebduqbTu1baO27dPGWDSmojEUjZlojERjIhoD0ZiHxjg0pqExDI1ZaItCWxLagtCWg7YYtKWgLQRtGWiLQFMCmgLQlH+m+DOlnyn8TNlnij5T8pmCz5Z7ttizpZ4t9GyZZ4s8W+LZAs+Wd7a4s6WdEQtDKwypMJTCEApDJwyZMFTCEAlDIwyJMBPCDAgzH8x4MNPBDAczG8xoMJPBCAYjF4xYMFLBCAUjE4xIMBLBCAQjD8w4MNPADAMzC8woMJPADAIzB8wYMFPAkLlG5RqRazSukbhG4RqBa/StkbdG3Rpxa7OtjbY22dpga3OtjbU21dpQazOtibQm0ZpAa/KsibMmzZowa7KsibImydoga3OsjbE2xdoQazOsjbA2wdoAa/Or8cAlPG8Jj1vC05bwsCU8awmPWsKTlvCgJTxnCY9ZslOW7JAlO2PJjliyE5bsgCU7X8mOV7LTlehwJTpbiY5WopOV6GAlOleJjlWiU5XoUCU6U8mOVLITlexAJTtPyY5TstOU7DAlO0vJjlKyk5TwKF88yRcP8sVzfPEYXzzFFw/xxTN88QhfPMHXDvC183vt+F47vdcO77Wze+3oXju51w7upXN76dheOrWXDu2lM3vpyF46sZcO7KXzeum4Xjut1w7rtbN67aheO6nXDuq1c3rtmF47pXdYTRtW04bVtGE1bVhNG1bThtW0YTVtWE0bVtMG1bRBNW1QTRtU0wbVtEE1bVBNG1TTBtW0ITVtSE0bUtOG1LQhNW1ITRtS04bUtCE1bUhNG1TTBtW0QTVtUE0bVNMG1bRBNW1QTRsWIEV0KFSHQnYodIdCeCiUh0J6KLSHQnwo04cyfijzhzKAKBOIMoIoM4gyhChTiCKGKHKIIogokogiiiiyiCKMKNKIIo4o8ogykCgTiTKSKDOJMpQoU4kylihziVKBRwkeNXgU4VGFRxkedXgU4lGJByketHgQ40GNBzke9HgQ5EGRB0keM3kM5TGVx1gec3kM5jGZx2ges3kM50GdB3ke9HkQ6EGhB4keNHoQ6UFfJgRmQmEmJGZCYyZEZkJlJmRmMmcmg2YyaSajZjJrJsNmMm0m42YybyYCZyJxJiJnInMmQmcidSZiZyJ3JoJnInkmo2cyeybDZzJ9JuNnMn8mA2hC3iT0TULgJBROQuIkNE5C5CRTTjLmJHNOMugkk04y6iSzTjLsJNNOIu4k8k4i8CQSTyLyJDJPIvQkUk8i9iRyTzL4JJNPMvoks08y/CTTT0L+IvQvQgAjFDBCAiM0MDIEI1MwMgYjczAyCCOTMDIKI7MwMgwj0jAiDiPyMCIQIxIxIhIjMjEiFCNSMSIWI3MxMhgjkzEyGiOzMULuIPQOQvAgFA9C8iAzDzL0IFMPMvYgcw8y+CCTDzL6ILMPIvwg0g8i/iDyDyIAIRIQIgIhMhAiBCFSEDIGIXMQMgghkxDCtHoYVw/z6mFgPUusZ5H1LLOehdaz1HoWW89y61lwPUuuR9H1KLsehdej9HoUX4/y61GAPUqwRxH2KMOehdizFHsWYw/TwGEcOMwDZ4HgLBGcRYKzTHAWCs5SwVksOMsFZ8HgKBkcRYOjbHAUDo7SwVE8OMoHRwHhKCEcRYSzjHAWEg7jkFkeMgtEZonILBKZZSKzUGSWisxikVkuMgpGRsnIKBoZZSOjcGSUjozikVE+MgpIRgnJLICVJbCyCFaWwcpCWFkKK4thZTmsKIgVJbGiKFaUxYrCWFEaK4pjRXmsybISk2UlJstKTJaVmCwrMVFWYqKsxERZiYmyEtP/yUr8cHe4vJ2/ffy/Hx9+PT+/XB7fDneHf59fXv/oP+0t25i2edtOHZf39/8BhLbmiQ==]]
|
||||
},
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = CoreData.world_concrete_tile,
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqd3c1uG0cQhdF3mTUJVDX7b/QqgReyNTEIUJRA0UkMQ+8eypGzCxCdlWHYTYKl4adC9b23fiyfT9+258vxfF3ufiwv5/vn/fVp//VyfHj7+1/LXS275fvbH6+75fjl6fyy3P12+4/Hr+f709t/uX5/3pa75XjdHpfdcr5/fPvby/XpvO3/vD+dlrdj54ft9kr5+mm3XI+n7Z+XeH56OV6PT+f399mX/PlG+8Prvy9z2X4/nreH/e1tv1y263Z7sf8+V/Bc2rmwY/huH/5wgcUMLGZgMcOKGVbMoGLmasX8dU7fL+1c2DF8tw9/uInFnFjMicWcVsxpxZxWzIHFHFjMgcUcVsxhxRxWzI7F7FjMjsXsVsxuxexWzIbFbFjMhsVsVsxmxWxWzIrFrFjMisWsVsxqxaxWzAMW84DFPGAxD1bMgxXzYMUs7x+OD6YeDDy44rmJ5wae63iu4bmK5w54jp8YO4ePC74bfjisJf7o8EnBBxO/B/i1w2+5UuXjGEsFZyo4U8GZCM5EcCaCMxGcieBMBCcOuhIHXYmDrrRBV9qgK23Q9X4Ma4k/OnxS8MHE7wF+7fBbrlT5OMZCwRkKzlBwBoIzEJyB4AwEZyA4A8GJQ+3EoXbiUDttqJ021E4caoeBMwycYeAMA2cYOMPAGQbOQHCGgXNFbq6IzRWpuRo0V2PmashcjZirAXM1XuK1Fd5a4aWV3VnZlZXdWK0EypU4uRImV6LkSpBciZErIXI1Qq4GyImAnAjIiYCcBshpgJwGyGmAnAbIaYDEq2i8icaLaLuHtmtou4WeBMhJgJwEyEmAnATISYCcBMhpgJwGyIGAHAjIgYAcBshhgBwGyGGAHAbIYYBEeQmqS1BcYtoSk5aYsmQQIAcBchAgBwFyECAHAXIQIIcBchggOwKyIyA7ArIbILsBshsguwGyGyC7ARIlY6gYQ8GY6cVMLmZqsU6A7ATIToDsBMhOgOwEyE6A7AbIboBsCMiGgGwIyGaAbAbIZoBsBshmgGwGSJSBogoURaCmATUJqClAGwGyESAbAbIRIBsBshEgGwGyGSCbAbIiICsCsiIgqwGyGiCrAbIaIKsBshogUdqNym4Udpuu22TdpuquBMhKgKwEyEqArATISoCsBMhqgKwGyF8ifD0Xdi5XPDfx3MBzHc81PFfx3AHPFTyHz0vi84KPCz4t+LDgs4KPCj4p+KDoc0LH7CGx97IPZlW0H5k9H/Yw2pNvXzP7TiNBEFjIR8Qx0h9/2eDvNvxVir+5sVH4cF9SsA8q2AcV7IMK9kEF+6CCfVDBPqhgH1SwD1K/pdot1W2JZkv0WqLVEp2WaLREnyXaLNFliSZL81iaxdIclmawNH+l2SvNXWnmSvNWmrUSnZVorCzWBxXrg4r1QcX6oGJ9ULE+qFgfVKwPKtYHJfZBiX1QYh+U2Acl9kGJfVBiH5TYByX2QWyfVhOgegDRAogOQDQAov8P7X/o/kPzH3r/0Ppnzj8z/pnvz2x/5voz0595/szyZ44/M/yh3w990tYHpfVBaX1QWh+U1gel9UFpfVBaH5TUB4W1QWFdUFgTFNYDhbVAYR1QWAMU1v+EtT+YgYAJCJh/YOkHln1gyQeWe2CpB5Z5YIkHlndgaQeUdUBJB5RzQCkHlHFACQeUb0DpBpRtQMkGlmtgqQZBXU5QkxPU4wS1OEEdTlCDE9TfBLU3Qd0NDnlwxoMjHpzw4IAH5zs43sHpDg53cLaDox2c7Nhgx+Y6NtaxqY4NdWymYyMdm+jYQIfmOTTOoWkODXNolkOjHJrk0CCH5jg0xrEpjg1xbIZjIxyb4NgAx+Y3Nr6x6Y0Nb2x2g1IeVPKgkAd1PCjjQRUPinhQw4MSHlTwoIAH9Tsm3zH1jol3TLtj0h1T7phwx3Q7Jtsh1Q6JdkizQ5IdUuyQYIf0OiTXIbUOiXVMq2NSHVPqmFDHdDom0zGVjol0TKNjEh1T6KBxB307aNsx146ZdsyzY5Ydc+yYYcf8OmbXMbcOmXXIq0NWHXLqkFGHfDpk0yGXDpl0yKNjFh1z6KC1H539aOw3X7/Z+s3Vb6Z+8/Sbpd8c/WboNz8/2fnJzU9mfvLyk5WfnPxk5CcfP9n4ycVvJn7z8GMIFGZAYQSUJUBZAJTlP1n8k6U/WfiTZT9Z9JMlP1HwE+U+UewTpT5R6BNlPlHkEyU+UeAT5T1Z3JOlPWFcKKaFYlioZYVaVKglhVpQqOWEWkyopYRaSKhlhFJEKCWEUkAo5YNSPCilg1I4KGWDUjQoJYNaMKjlgmKwPObKY6y8pcpbqLxlylukvCXKW6C85clbnLylyVOYPGXJU5Q8JclTkDzlyFOMPKXIU4g8ZchbhLwlyOMKItxAhAuIbP+QrR+y7UO2fMh2D9nqIds8ZIuHbO8QrR2irUO0dIh2DtHKIdo4RAuHaN8QrRuibUO2bMh2DeGyStxViasqbVOlLaq0PZW2ptK2VNqSSttRaSsqbUMlLaik/ZS0npK2U9JyStpNSaspaTMlLaakvZS2ltK2Uuq6c912rsvOcdc5rjrHTee46Bz3nOOac9xyjkvOcce5rTi3Dee24Nz2m9t6c9tubsvNbbe5rTa3zea42Bz3mqe6BdUuqH5BNAyiYxAtg+gZRNMgugbRNoi+QTQOmnPQrIPmHTTzoLkHzT5o/kEzEJqD0CyE6CFEE6H5UNKMKGlOlCQrSpIXJcmMkqZvThM4pymckyTOSRrnJJFzmjoyTR6Zpo9MEkgmKSSTJJJp2qo0cVWauipJXpWkr0oSWKUpM9KkGWnajCRxRpI6I0mekXavm3axm3azm3S1m3S3m3S5m3YrlHYtlHYvlHQxlHQzlHQ1lDZTThsqp02Vk8bKSXPlpMFysTlUsTlUsTlUoTlUoTlU+R9zqE+75XjdHm//9vn0bXu+HM/XZbf8sV1efr5OmVnHWsZhjJZRX1//Bgu6MZo=]],
|
||||
},
|
||||
{
|
||||
type = 'static',
|
||||
force = 'environment',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqVmtFq20AQRf9ln+Wg1e5qtf6VEorTiGJwZBM7bUPwv9dOSlqoLzPnKQisw155dD2ZO2/hYfcyH563yyms38Jx2RxWp/3q+/P28Xr9K6zz0IXX659zF7bf9ssxrL9cPrj9vmx214+cXg9zWIftaX4KXVg2T9er42m/zKufm90uXG9bHucLKZ7vuzAvp+1pO39Q3i9evy4vTw/z8+UDt+7vwmF/vNyyX/4caDXclfcjrYb+rpzP3X+cAXJiu81JLo6JyQyjVBWqarrNGSmn3uZU+HQEZoIYoapRVeNtTuwpqAhQhMIUZ4AcJSxRYVmAMgUlASpQmeKMkKOE+Sp6FftPUhSkyUmKJslZ15MFGpx13UyQ06VHE+S06WqCnJWdTZCzsosJwl49CBA2a3UiZ20nE0T9WnEa5IgnlHx1bepKvrI2v/rkq2qzFpOvqM2XI/lq2nxbk6+kTftIvoo2/Sz5Ctp22OQraNv0U8OmLzq93FOS6jwjfEiKM9CHrZQlqky0ezlTkGg/c4HSFGeEHCWsUmGi38u4BxENaG5QmeCUHnKEsBKpMNHvlYGCRANaElSmOBlylDBv+/HpaeLHtTjbjzhZIG9VNwvkrerRAnnduhqg0WvW2QJ567pYIG9dJwvkdevBAmG3ViDq1orjdGvzCTm7EPMBOZsQ86t3erVVi9Xp1dbLUZ0NiPW2VmcDYvlQdTq1ZUPVOdOzDLZSp1YcatSKQ31acSbororToN0LztRDb1WcCM1ecahFKw51aMWhBq040J8VZmS2qjCVubzCTMxUFaYxjxeY1jNLVZjIHF5hoDErDPRlhYG2rDAFvg2in28j5Ih+vsFZh8JMDKNU0TmHCjZ6OuaQkQ0cc0gOHHNIYXTKURWI2vKkQNCXJQdOOaQwOuVoCkSnHGoyFXs45pCgCOccSlqkcw6ZIcUBBlualFiKpEGZ5VoaVFiKpEEjy7U0qLIUSYMmlmtpEAzHJWiA4bgKbaI3REzmiVg6rg/Edj30eTKKozSnoBhJc0YUa2lORTGS5kwo1tKchmIkyXHGh6afOeND22ET7EE0CO57yO2KBPc95HpFYvsemsP2PbSwCoWpfs8ZIf4FyRUdFopLjjNANIVluJGndrxihit5assrZujTksOW8rQwuOmhdgRjhpseakswZraXpzls0eND2H33sQi6/mettAs/5ufj+x3DdDleG2qqtVz+uTmffwPQ9nqN]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Public.lonely_storage_tank = {
|
||||
name = 'lonely_storage_tank',
|
||||
width = 4,
|
||||
height = 6,
|
||||
components = {
|
||||
{
|
||||
type = 'static_destructible',
|
||||
force = 'ancient-friendly',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqFkVsKwjAQRfcy34m0aWs1WxGRqEMJ2klIUrFI9m5axQdW/QoD9xxuZi6wPXZonaYA8gKelOXB8Mbp/TCfQRYMepDzyEDvDHmQqxTTDanjEAi9RZCgA7bAgFQ7TD4YpxrkQdEBBpD2mEx5XDNACjpovHnGod9Q127RpcDDYLvWJp81PoUN3avwfFaNbbiIkX3gYrrApya7a9I75SmeNXT63fcaYpov//HZb776w7/haaXj8uXLIRmc0PkREIu8rJeiLuq6yrMyxiu0uZ7v]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Public.swamp_lonely_storage_tank = {
|
||||
name = 'swamp_lonely_storage_tank',
|
||||
width = 3,
|
||||
height = 3,
|
||||
components = {
|
||||
{
|
||||
type = 'static_destructible',
|
||||
force = 'ancient-friendly',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNptj80KwjAQhN9lz4nYH9uaVxGR1C4l2G5KshVLybubRA8ePC0DM9/O7NBPKy7OEIPawZNeJFs5OjMk/QJVCdhANUGAuVvyoC7RZkbSUzLwtiAoMIwzCCA9J+XZOj2iZE0PSEEaMJKKcBWAxIYNfjhZbDda5x5dNPwnCFisjyFL30ryeDjlVvGGBM3v1c8UAU90PifKrqjbc9nWVVOfyy6EN3scTtM=]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.covered1 = {
|
||||
name = 'covered1',
|
||||
width = 17,
|
||||
height = 15,
|
||||
components = {
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = 'orange-refined-concrete',
|
||||
offset = {x = -9, y = -8},
|
||||
bp_string = [[0eNqVmMGKwjAURf8l6wreJG2S/srgwtEgAW1L7Qwj0n8fqy5m4YBnJcKxHrxc7sOr+Tx+5WEs3WTaqzl322E19avDWPbL+x/TKlXmcnsJc2XKru/Opv24geXQbY8LMl2GbFpTpnwylem2p+XdjduNecpm+VC3z8tz5k1lpnLMjwcM/blMpe+e37K+f8l6fvWEf2AR2BLYEdgTuCZwQ+BA4EjghEJhEaIMhUIUSlEoRqEc9WaQIh0Q6YBIB0Q6INIBkQ6IdECkAyIdEOmAUAeEOiDUAaEOCHVAqANCHbCkA5Z0wCJri6wdsXbE2iFrh6w9sfbE2iNrj6xrYl0T6xpZ18i6IdYNsW6QdYOsA7EOxDog64CsI7GOxDoi64isE7FOxDoh68RuFnS4C13uYseW4LXFzi12b8GJZBspNJJCKyk2k2I7KTSUQkspNpViWyk0lkJrKTaXYnspNJhCiyk2mWKbKTSaQqspNptiuyk0nELL+aQtoh2iPaJrRLNfMCA6IjqxdGCYLE2xOMXyFAtULNG3S4HuMqHD7ElbRDtEe0TXiGa/YEB0RHRi6cAwWZpicYrlKRaoWKKvS7GpHv+Tt3/+da/Mdx7P9wfYKB+SDd41Ptk4z7+pVIVy]],
|
||||
},
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = 'green-refined-concrete',
|
||||
offset = {x = -1, y = 2},
|
||||
bp_string = [[0eNqV0tsKwjAMBuB3yXWF9bCDfRXxYm5lFLa2tFUco+9uO70QVDCXgS9/CMkGl/mqnNcmgtwgmN4doj1MXo+lvoNsCawg60RAD9YEkKfM9GT6uYC4OgUSdFQLEDD9UqrsBq+igtJkRpVTaDoTiHpWzwBng47amteMap8h0reED0wxmGEw33GFwRSDGQZzDP5zQYHBNQY3v3E+/P4e8u3VCNyUD3s766hoj6wVjPOublJ6AP6T06c=]],
|
||||
},
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = 'out-of-map',
|
||||
offset = {x = -7, y = -6},
|
||||
bp_string = [[0eNqd2s1Kw0AUhuF7mXWEfnPO/OVWxEXVIIGaljaKIrl3G3XhQqWvqxA4nUDOs3qbt3C7exoOx3GaQ/8WTtP2cDXvrx6O4/16/xJ6pS68ni+2dGG820+n0F+fB8eHabtbR+bXwxD6MM7DY+jCtH1c785zd8dhHsL6o+l+WM9Zbrowj7vh84DD/jTO4376esrm4yGb5acTfhkWGY5k2Miwk+FEhjMZLmS4kuGGlsJWiHaoC5coYknEkoglEUsilkQsiVgSsSRiScSSkCUhS0KWIrEUiaVILEViKRJLkViKxFIkliKxFImliCxFZCkiS0YsGbFkxJIRS0YsGbFkxJIRS0YsGbFkyJIhS4YsObHkxJITS04sObHkxJITS04sObHkxJIjS44sObKUiKVELCViKRFLiVhKxFIilhKxlIilRCwlZCkhSwlZysRSJpYysZSJpUwsZWIpE0uZWMrEUiaWMrKUkaVCdBSioxAdhegoREchOgrRUYiOQnQUoqMgHQXpqERHJToq0VGJjkp0VKKjEh2V6KhERyU6KtJRkY5GdDSioxEdjehoREcjOhrR0VDVQSlWqMUKxVihGiuUY4V6rFCQ1eYf77ui6ca2A5d56TZZaGWllaVW1lpZbGW1leVW1ltZcGXFFSZX2FxRRhXqqEIhVaikCqVUoZYqFFOFaqpQThXqqWJBVayoCkVSoUoqlEmFOqlQKBUqpUKpVKiVCsVSoVoqlktl/5Fy8Z+CqJgKJVOhZioUTYWqqVA2FeqmQuFUqJwKpVOxdioWT/VXPb3pPr906L99N9GF5+F4+jggVnlpsbhlb7Euyzuk5qn3]],
|
||||
},
|
||||
{
|
||||
type = 'static',
|
||||
force = 'environment',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqlmNtuozAQht/F11Ax+IR5lVW1Io0VIRGDwOw2qnj3hbKHSGVghr2KUODz2Hwe+PkQl2b0XV+HKMoPMYSqS2Ob3vr6uhy/ixJsIh7zj54SUb+1YRDlt/nE+haqZjklPjovSlFHfxeJCNV9ORpiG3z6s2oasVwWrn4hTa+J8CHWsfYr5fPg8T2M94vv5xO2rk9E1w7zJW34XVD2oteKXvQ0JV8gOQuSbUMkCQL7EEWC5PsQTYLIfYghQdQ+xJIgeh9SkCBmH+JIELsPgYxEKQ4oNGfdAeWftP696/0wpOO8Z/pb386/6cU3ccO+Z4eTP/uwHWM3RrE1CFHqA6uBpjUceA00seHAbKCpDQduA01uOLAbaHqD2W9h4HgYpJo8Y7VCjVCAVwyG4fVli1Aki2IQiuJNCStG8zBYNYY1J4dQLItSIJTifxqRe25EdUD6UM60G5mwzHgYZMaS+dKBbFnJ0xuw9w75Zf2btppvwM6qA1C6v2Q6j06UKT06U571y+NkE2NPCPsXKj+Fvda9f1v/zo/1lWe2iCWMuHPvHNkKd35iKqO7lyPDGMIwcKbFSHQBDWEBVc6UFrFNyTO1G0Lt+HIp3j5RSOWalWhQjGFlGhRjWakGxRSsXINiHCvZYBidsbINigFWukExOSveoBjJyjcohvj0OdJYa16GQTmGF2JQjuWlGJRT8GIMynG8HINxDPPlauW8JutnoPLpo1Iifvh+WJ9BBSjrcqukUS4vpukXJhD2Zw==]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.covered1.red_chest = {x = 2, y = 5}
|
||||
Public.covered1.blue_chest = {x = 2, y = 6}
|
||||
Public.covered1.walls = {
|
||||
{x = -8, y = -5},
|
||||
{x = -8, y = -4},
|
||||
{x = -8, y = -3},
|
||||
{x = 8, y = -5},
|
||||
{x = 8, y = -4},
|
||||
{x = 8, y = -3},
|
||||
}
|
||||
|
||||
Public.covered1b = {
|
||||
name = 'covered1b',
|
||||
width = 17,
|
||||
height = 15,
|
||||
components = {
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = 'orange-refined-concrete',
|
||||
offset = {x = -7, y = -6},
|
||||
bp_string = [[0eNqVmM1qg0AURt9l1gby3ev/q5QsbDMUwaiobROC797YlpJFaXtWInwzzmHO4rtew2P3Esep7ZdQX8PcN+NuGXbPU3vc3s+hVpaEy+3haxLap6GfQ/1wC7bPfdNtkeUyxlCHdomnkIS+OW1v8zL0cffWdF3YlvXHuO20Jn8ujOdxivO864bmGKe7xbYekrC0Xfz8/jjM7dIO/dch9x9n3K/f+9wO+jTFJYbtmz+GRcJGwk7CKQlnJJyTcEHCJQlX6FLYFaI71D8vUcQlEZdEXBJxScQlEZdEXBJxScQlEZeEXBJyScglIy4ZccmIS0ZcMuKSEZeMuGTEJSMuGXHJkEuGXDLkkhOXnLjkxCUnLjlxyYlLTlxy4pITl5y45MglRy45ciklLqXEpZS4lBKXUuJSRgAzApgRwIwAZgQwJ4A5AcwJYE4AcwJYEMCCABYEsCCABQEsCWBJAEsCWBLAkgBWBLAigBUBrAhghYo0GjuF5k6hwVNo8hQaPcUGIjYRsZGIzURsKEJVXairC5V1obYuVNeFSqRQixSqkUI9UqhICtUboX4jVHCEGo5+qTiH5PNPWX33wy4Jr3GaP9ZbqbSorEjNvczydX0HDBNakQ==]],
|
||||
},
|
||||
{
|
||||
type = 'static',
|
||||
force = 'ancient-friendly',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqV1e9qwyAQAPB3uc+mRBOjyauMMdJFipBqiHZrKL77YsqgjPnvUzi4+0W543zAeb6JZZXKwvAAo8alsrq6rHLy8R0GTBFs+6dxCOSnVgaGtz1RXtQ4+xS7LQIGkFZcAYEarz4yVitRfY/zDL5MTcJLDiULxX1ZhTHVrMdJrC/FxL0jEMpKK8XzCEewfajb9bxnDvi/nyNYtNlLtPq9zel5nfpEnT/OH4RkIXUcabKQJo60WQiJIzQLYXGky0L6OMKyEB5HeF6LEz3u85REk3GdxyQ6hDPHNjEtOG9wcZtgmqL5bwNKW6R0AYUWKTSgdEUKDyisSGEBhRcpONSkvojpA5uuLjsMCTC4jMGe2Tf5sfWHl8cHwZdYzVFBOG5ZT1hLmobTzrkfNM8jsg==]],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.covered1b.market = {x = -2, y = -5}
|
||||
Public.covered1b.steel_chest = {x = 1, y = -5}
|
||||
Public.covered1b.wooden_chests = {
|
||||
{x = -5, y = 1},
|
||||
{x = -4, y = 3},
|
||||
{x = -5, y = 5},
|
||||
}
|
||||
|
||||
|
||||
Public.maze_defended_camp = {
|
||||
name = 'maze_defended_camp',
|
||||
width = 20,
|
||||
height = 20,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'static_destructible',
|
||||
force = 'ancient-hostile',
|
||||
offset = {x = 0, y = 0},
|
||||
bp_string = [[0eNqVkVEKgzAQRO+y3xEaa7TNVUopWhcJ6CbEpFQkd2+iFAq1UL+WgZnHMDtD03s0VpEDOcNItcmczjqr2qSfIHnJYEonMFB3TSPISzSqjuo+WdxkECQohwMwoHpIqvOUOW8tOkgxajGRwpUBklNO4UpZxHQjPzRoo2Erz8DoMUY0vQutfUJgX4D8P4D4TTjuqSC2CMWuDhERR1nGkx+vYPBAOy72/MSL6pxXggt+LA8hvAD1/I5u]],
|
||||
},
|
||||
{
|
||||
type = 'entities_randomlyplaced_border',
|
||||
name = 'land-mine',
|
||||
force = 'ancient-hostile',
|
||||
offset = {x = 0, y = 0},
|
||||
count = 20,
|
||||
large_r = 10,
|
||||
small_r = 7,
|
||||
},
|
||||
{
|
||||
type = 'entities_randomlyplaced',
|
||||
name = 'wooden-chest',
|
||||
force = 'ancient-friendly',
|
||||
offset = {x = 0, y = 0},
|
||||
count = 13,
|
||||
r = 4,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.maze_undefended_camp = {
|
||||
name = 'maze_undefended_camp',
|
||||
width = 20,
|
||||
height = 20,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_randomlyplaced_border',
|
||||
name = 'land-mine',
|
||||
force = 'ancient-hostile',
|
||||
offset = {x = 0, y = 0},
|
||||
count = 10,
|
||||
large_r = 10,
|
||||
small_r = 7,
|
||||
},
|
||||
{
|
||||
type = 'entities_randomlyplaced',
|
||||
name = 'wooden-chest',
|
||||
force = 'ancient-friendly',
|
||||
offset = {x = 0, y = 0},
|
||||
count = 7,
|
||||
r = 4,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.maze_mines = {
|
||||
name = 'maze_mines',
|
||||
width = 24,
|
||||
height = 24,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_randomlyplaced',
|
||||
name = 'land-mine',
|
||||
force = 'ancient-hostile',
|
||||
offset = {x = 0, y = 0},
|
||||
count = 10,
|
||||
r = 12,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.maze_labs = {
|
||||
name = 'maze_labs',
|
||||
width = 12,
|
||||
height = 12,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_randomlyplaced',
|
||||
name = 'lab',
|
||||
force = 'ancient-friendly',
|
||||
offset = {x = 0, y = 0},
|
||||
count = 4,
|
||||
r = 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.maze_worms = {
|
||||
name = 'maze_worms',
|
||||
width = 20,
|
||||
height = 20,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_randomlyplaced',
|
||||
name = 'random-worm',
|
||||
force = 'enemy',
|
||||
offset = {x = 0, y = 0},
|
||||
count = 20,
|
||||
r = 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Public.maze_belts_1 = {
|
||||
name = 'maze_belts_1',
|
||||
width = 23,
|
||||
height = 23,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_grid',
|
||||
force = 'ancient-friendly',
|
||||
name = 'express-transport-belt',
|
||||
direction = defines.direction.east,
|
||||
offset = {x = 0, y = 0},
|
||||
width = 23,
|
||||
height = 23,
|
||||
},
|
||||
},
|
||||
}
|
||||
Public.maze_belts_2 = {
|
||||
name = 'maze_belts_2',
|
||||
width = 23,
|
||||
height = 23,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_grid',
|
||||
force = 'ancient-friendly',
|
||||
name = 'express-transport-belt',
|
||||
direction = defines.direction.west,
|
||||
offset = {x = 0, y = 0},
|
||||
width = 23,
|
||||
height = 23,
|
||||
},
|
||||
},
|
||||
}
|
||||
Public.maze_belts_3 = {
|
||||
name = 'maze_belts_3',
|
||||
width = 23,
|
||||
height = 23,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_grid',
|
||||
force = 'ancient-friendly',
|
||||
name = 'express-transport-belt',
|
||||
direction = defines.direction.south,
|
||||
offset = {x = 0, y = 0},
|
||||
width = 23,
|
||||
height = 23,
|
||||
},
|
||||
},
|
||||
}
|
||||
Public.maze_belts_4 = {
|
||||
name = 'maze_belts_4',
|
||||
width = 23,
|
||||
height = 23,
|
||||
doNotDestroyExistingEntities = true,
|
||||
components = {
|
||||
{
|
||||
type = 'entities_grid',
|
||||
force = 'ancient-friendly',
|
||||
name = 'express-transport-belt',
|
||||
direction = defines.direction.north,
|
||||
offset = {x = 0, y = 0},
|
||||
width = 23,
|
||||
height = 23,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Public.maze_treasure = {
|
||||
name = 'maze_treasure',
|
||||
width = 3,
|
||||
height = 3,
|
||||
components = {
|
||||
{
|
||||
type = 'tiles',
|
||||
tile_name = 'cyan-refined-concrete',
|
||||
offset = {x = -1, y = -1},
|
||||
bp_string = [[0eNqVksEKgzAMht8l5wqmzrn1VcYOToMEtC21GxPpu691O+wwYb0EAl/+fJCscBvvZB1rD2qFWbe28KYYHPepf4KqBCyxBgHcGT2DukSMB92OCfCLJVDAniYQoNspdZHrHHmCNKR7iikYrgI8j/QOsGZmz0Z/dpTbjjL8StiBMQeW/8GYo4E5GpijIXM0ZI6G3NeI59mOqL4eQsCD3LyNyxMemrNsaqyxOpYhvAAnDLaS]],
|
||||
},
|
||||
{
|
||||
type = 'entities',
|
||||
name = 'steel-chest',
|
||||
force = 'ancient-friendly',
|
||||
offset = {x = 0, y = 0},
|
||||
instances = {
|
||||
{position = {x = 0, y = 0}},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return Public
|
40
maps/pirates/structures/island_structures/roc/roc.lua
Normal file
40
maps/pirates/structures/island_structures/roc/roc.lua
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
local Data = require 'maps.pirates.structures.island_structures.roc.data'
|
||||
|
||||
local Public = {}
|
||||
Public.shelter1 = {}
|
||||
Public.shelter1.Data = Data.shelter1
|
||||
Public.shelter2 = {}
|
||||
Public.shelter2.Data = Data.shelter2
|
||||
Public.covered1 = {}
|
||||
Public.covered1.Data = Data.covered1
|
||||
Public.covered1b = {}
|
||||
Public.covered1b.Data = Data.covered1b
|
||||
Public.lonely_storage_tank = {}
|
||||
Public.lonely_storage_tank.Data = Data.lonely_storage_tank
|
||||
Public.swamp_lonely_storage_tank = {}
|
||||
Public.swamp_lonely_storage_tank.Data = Data.swamp_lonely_storage_tank
|
||||
Public.maze_labs = {}
|
||||
Public.maze_labs.Data = Data.maze_labs
|
||||
Public.maze_defended_camp = {}
|
||||
Public.maze_defended_camp.Data = Data.maze_defended_camp
|
||||
Public.maze_undefended_camp = {}
|
||||
Public.maze_undefended_camp.Data = Data.maze_undefended_camp
|
||||
Public.maze_mines = {}
|
||||
Public.maze_mines.Data = Data.maze_mines
|
||||
Public.maze_worms = {}
|
||||
Public.maze_worms.Data = Data.maze_worms
|
||||
Public.maze_belts_1 = {}
|
||||
Public.maze_belts_1.Data = Data.maze_belts_1
|
||||
Public.maze_belts_2 = {}
|
||||
Public.maze_belts_2.Data = Data.maze_belts_2
|
||||
Public.maze_belts_3 = {}
|
||||
Public.maze_belts_3.Data = Data.maze_belts_3
|
||||
Public.maze_belts_4 = {}
|
||||
Public.maze_belts_4.Data = Data.maze_belts_4
|
||||
Public.maze_treasure = {}
|
||||
Public.maze_treasure.Data = Data.maze_treasure
|
||||
|
||||
|
||||
|
||||
return Public
|
232
maps/pirates/structures/structures.lua
Normal file
232
maps/pirates/structures/structures.lua
Normal file
@ -0,0 +1,232 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
local Loot = require 'maps.pirates.loot'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
BOATS = 'Boats',
|
||||
ISLANDSTRUCTURES = 'IslandStructures',
|
||||
}
|
||||
Public.enum = enum
|
||||
Public[enum.BOATS] = require 'maps.pirates.structures.boats.boats'
|
||||
Public[enum.ISLANDSTRUCTURES] = require 'maps.pirates.structures.island_structures.island_structures'
|
||||
|
||||
|
||||
function Public.post_creation_process(special_name, components)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
for _, c in pairs(components) do
|
||||
local type = c.type
|
||||
local force_name = c.force_name
|
||||
-- local force
|
||||
-- if force_name then force = game.forces[force_name] end
|
||||
|
||||
if type == 'static' then
|
||||
for _, e in pairs(c.built_entities) do
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
end
|
||||
end
|
||||
elseif type == 'static_destructible' then
|
||||
for _, e in pairs(c.built_entities) do
|
||||
if e and e.valid then
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
end
|
||||
end
|
||||
-- elseif type == 'plain' then
|
||||
-- for _, e in pairs(c.built_entities) do
|
||||
-- --
|
||||
-- end
|
||||
elseif type == 'static_inoperable' then
|
||||
for _, e in pairs(c.built_entities) do
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.operable = false
|
||||
end
|
||||
end
|
||||
elseif type == 'entities' or type == 'entities_grid' then
|
||||
for _, e in pairs(c.built_entities) do
|
||||
if e and e.valid then
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.destructible = false
|
||||
end
|
||||
end
|
||||
elseif type == 'entities_randomlyplaced' or type == 'entities_randomlyplaced_border' then
|
||||
for _, e in pairs(c.built_entities) do
|
||||
if e and e.valid then
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
end
|
||||
end
|
||||
-- elseif type == 'entities_minable' then
|
||||
-- for _, e in pairs(c.built_entities) do
|
||||
-- --
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
for _, e in pairs(c.built_entities) do
|
||||
if e and e.valid then
|
||||
e.update_connections()
|
||||
if e.name == 'iron-chest' then
|
||||
local inv = e.get_inventory(defines.inventory.chest)
|
||||
local loot = Loot.iron_chest_loot()
|
||||
for i = 1, #loot do
|
||||
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()
|
||||
for i = 1, #loot do
|
||||
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()
|
||||
for i = 1, #loot do
|
||||
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
|
||||
local inv = e.get_inventory(defines.inventory.lab_input)
|
||||
local loot = Loot.maze_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
|
||||
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
|
||||
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
|
||||
end
|
||||
|
||||
if force_name and string.sub(force_name, 1, 15) 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})
|
||||
else
|
||||
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
|
||||
if e.name == 'oil-refinery' then
|
||||
e.set_recipe('advanced-oil-processing')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.try_place(structureScope, specialsTable, left_top, areawidth, areaheight, placeability_function)
|
||||
local structureData = structureScope.Data
|
||||
|
||||
local attempts = 6
|
||||
local succeeded = false
|
||||
|
||||
while attempts > 0 and (not succeeded) do
|
||||
attempts = attempts - 1
|
||||
|
||||
local structure_topleft = {
|
||||
x = left_top.x + Math.random(areawidth + 1 - structureData.width) - 1,
|
||||
y = left_top.y + Math.random(areaheight + 1 - structureData.height) - 1,
|
||||
}
|
||||
local structure_center = {
|
||||
x = structure_topleft.x + structureData.width/2,
|
||||
y = structure_topleft.y + structureData.height/2,
|
||||
}
|
||||
local structure_topright = {
|
||||
x = structure_topleft.x + structureData.width,
|
||||
y = structure_topleft.y,
|
||||
}
|
||||
local structure_bottomleft = {
|
||||
x = structure_topleft.x,
|
||||
y = structure_topleft.y + structureData.height,
|
||||
}
|
||||
local structure_bottomright = {
|
||||
x = structure_topleft.x + structureData.width,
|
||||
y = structure_topleft.y + structureData.height,
|
||||
}
|
||||
|
||||
if placeability_function(structure_topleft) and placeability_function(structure_topright) and placeability_function(structure_bottomleft) and placeability_function(structure_bottomright) and placeability_function(structure_center) then
|
||||
specialsTable[#specialsTable + 1] = {
|
||||
position = structure_center,
|
||||
components = structureData.components,
|
||||
width = structureData.width,
|
||||
height = structureData.height,
|
||||
name = structureData.name,
|
||||
}
|
||||
succeeded = true
|
||||
if _DEBUG then
|
||||
log('structure_yes: ' .. structureData.name .. ' at ' .. structure_center.x .. ', ' .. structure_center.y)
|
||||
end
|
||||
-- else
|
||||
-- -- if _DEBUG then
|
||||
-- -- log('structure_no: ' .. structureData.name .. ' at ' .. structure_center.x .. ', ' .. structure_center.y)
|
||||
-- -- end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.tryAddStructureByName(specialsTable, name, p)
|
||||
local structureScope = Public[enum.ISLANDSTRUCTURES][Public[enum.ISLANDSTRUCTURES].enum.ROC][name] or Public[enum.ISLANDSTRUCTURES][Public[enum.ISLANDSTRUCTURES].enum.MATTISSO][name]
|
||||
|
||||
if not structureScope then
|
||||
log('Couldn\'t find structure data for ' .. name)
|
||||
return {}
|
||||
else
|
||||
local structureData = structureScope.Data
|
||||
|
||||
specialsTable[#specialsTable + 1] = {
|
||||
position = p,
|
||||
components = structureData.components,
|
||||
width = structureData.width,
|
||||
height = structureData.height,
|
||||
name = structureData.name,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
267
maps/pirates/surfaces/cabin.lua
Normal file
267
maps/pirates/surfaces/cabin.lua
Normal file
@ -0,0 +1,267 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- 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 SurfacesCommon = require 'maps.pirates.surfaces.common'
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
DEFAULT = 'Default',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
Public.Data = {}
|
||||
|
||||
Public.Data.width = 16
|
||||
Public.Data.height = 24
|
||||
|
||||
Public.Data.cabin_whitebelts_lrtp_order = {
|
||||
{x = -5.5, y = -10.5, direction = defines.direction.north, type = 'input'},
|
||||
{x = -4.5, y = -10.5, direction = defines.direction.north, type = 'input'},
|
||||
{x = -3.5, y = -10.5, direction = defines.direction.north, type = 'input'},
|
||||
{x = -5.5, y = 10.5, direction = defines.direction.south, type = 'output'},
|
||||
{x = -4.5, y = 10.5, direction = defines.direction.south, type = 'output'},
|
||||
{x = -3.5, y = 10.5, direction = defines.direction.south, type = 'output'},
|
||||
}
|
||||
|
||||
Public.Data.car_pos = {x = 7, y = 0}
|
||||
|
||||
Public.Data.static_entities_bp = [[0eNqlmt1u4jAQhd/F16HKOP4Lr1JVK1qsbiSaoCTstqp49yWwW9EtJ/FxLyPIx9g+4zP28K4ed4e475t2VOt3NbSb/WrsVs99s52eX9VaXKHe1FqbY6Gap64d1Pr+9MXmud3spq+Mb/uo1qoZ44sqVLt5mZ5+d902tqunn3EY1fRiu40T61gsvhpf930chtXYb9ph3/Xj6jHuriH6+FCo2I7N2MRLMOeHtx/t4eUx9qdfuR1GofbdcHqpa/+N7M6eh1be2eMU2H8YnYgp5zFVIqaax5hEjJ7H2ESMnce4RIyZx/hEjJ/HhESMm8fUiZh6HiNlIicscJJ1vCBkSVWyLEhZUrUsC2KWVDXLgpwlVc+yoERxZLYL4HiSowEnLG2IMNcQsWanCoB0yYLAXGkh56oCHHanNoBT0XOuF4gmm4jGamlitRCj+0LcdZvt6aMb+8MHqFDbpo9Plw9PhL9W3h3G/WEy668/41nVoHgDC0JTWZOyscDgS5LjAEeyxYKIOpuIxlplyw8R+RSxV6P+pEN9i2+zN1IUscuOGBF9cgp6MPKPDGxakIAV7yj+KuzPCX+LX9N8x/BNye5TNmefMsJuLyD5jGZBQB2mIvcXDziG5ATAsdm7CiLmZ1RI2QMMm18hI78M7UtoNuhCDSy4ZY2pBhy2ThN0+Mz3I4issqVzRi5qxxpSOzewy+KxyecYuzQhjq7OEYmu2JB+AqsfcGCwbMUm4AjjynwhIqTkC1GnCNFpVog6Q4iONRsB1bVj3UZAve/y7QYi8/1GTNJasYZzA5uwVoHeNNBi0ZaDptbzlwMgJk+7DqifPHs9IKCi8/n3AxCZf/qRpOOPt6wSc84WnjcdNCG06cBlp10HlFGedh1Q2IVvuA5CfsN1kkrnQLtOTu0cKnrV0YQYmgSWPVh22UH5E9irZY3aHD5bPxBJH1ogibcQMF81e2zRoFysWQfRoLardf5lPIqNVjwMjlY8jMmSjVMNrLumFY9AnmyeQlAg26cQVJMNVASSsiR7qJgkZBsVkzTZScWkimymYpIh26mYZNmGKkY5tqWKUZ5tqmJUYNuqGMV3C8+oh+Lyd4711f9KCvUr9sOlFghifK29FSuVK4/HPzs+Pbo=]]
|
||||
|
||||
Public.Data.operable_entities_bp = [[0eNqV1NtqxCAQBuB3mWtTVnP2VUopyWbYCskY1G0bFt+9MUthKW4a7xzw/xyN5gb9eMXZKHIgb2CpmzOns4tRQ6i/QfKKwQJSFJ6BOmuyIF/XiepC3RimuGVGkKAcTsCAuilUX1oPSNn5A62DEKQBg+XZv1FnOrKzNi7rcXwMC//GAMkpp/DexFYs73SdejSrHl+ewaztGtL0u6PTS7ntKQx8aOkPJFKhNu7kRx2+7xRHHbHvlEedfN+pkg+ax6E6GRJxqEmGijjUJkN5HOKn1I/2rCXOU6/RU0mkXoC7tL677Y3Kh58Fg080douIhhd1K+pC5HlTVt7/AARAZgM=]]
|
||||
|
||||
Public.Data.cabin_splitters = {
|
||||
{x = -5, y = 9.5, direction = defines.direction.north, type = 0},
|
||||
{x = -4, y = 8.5, direction = defines.direction.north, type = 0},
|
||||
{x = -3, y = 7.5, direction = defines.direction.north, type = 0},
|
||||
{x = -5, y = 7.5, direction = defines.direction.north, type = 1},
|
||||
{x = -4, y = 6.5, direction = defines.direction.north, type = 1},
|
||||
{x = -3, y = 5.5, direction = defines.direction.north, type = 1},
|
||||
{x = -5, y = 5.5, direction = defines.direction.north, type = 2},
|
||||
{x = -4, y = 4.5, direction = defines.direction.north, type = 2},
|
||||
{x = -3, y = 3.5, direction = defines.direction.north, type = 2},
|
||||
{x = -5, y = 3.5, direction = defines.direction.north, type = 3},
|
||||
{x = -4, y = 2.5, direction = defines.direction.north, type = 3},
|
||||
{x = -3, y = 1.5, direction = defines.direction.north, type = 3},
|
||||
{x = -5, y = 1.5, direction = defines.direction.north, type = 4},
|
||||
{x = -4, y = 0.5, direction = defines.direction.north, type = 4},
|
||||
{x = -3, y = -0.5, direction = defines.direction.north, type = 4},
|
||||
{x = -5, y = -0.5, direction = defines.direction.north, type = 5},
|
||||
{x = -4, y = -1.5, direction = defines.direction.north, type = 5},
|
||||
{x = -3, y = -2.5, direction = defines.direction.north, type = 5},
|
||||
{x = -5, y = -2.5, direction = defines.direction.north, type = 6},
|
||||
{x = -4, y = -3.5, direction = defines.direction.north, type = 6},
|
||||
{x = -3, y = -4.5, direction = defines.direction.north, type = 6},
|
||||
{x = -5, y = -4.5, direction = defines.direction.north, type = 7},
|
||||
{x = -4, y = -5.5, direction = defines.direction.north, type = 7},
|
||||
{x = -4, y = -8.5, direction = defines.direction.north, type = 7},
|
||||
{x = -5, y = -9.5, direction = defines.direction.north, type = 7},
|
||||
{x = -3, y = -7.5, direction = defines.direction.north, type = 8},
|
||||
{x = 0.5, y = -7, direction = defines.direction.west, type = 8},
|
||||
}
|
||||
|
||||
Public.Data.output_chest = {x = 3.5, y = -6.5}
|
||||
Public.Data.backup_output_chest = {x = 3.5, y = -7.5}
|
||||
|
||||
Public.Data.input_chests = {
|
||||
{x = 0.5, y = 6.5},
|
||||
{x = 0.5, y = 4.5},
|
||||
{x = 0.5, y = 2.5},
|
||||
{x = 0.5, y = 0.5},
|
||||
{x = 0.5, y = -1.5},
|
||||
{x = 0.5, y = -3.5},
|
||||
{x = 0.5, y = -5.5},
|
||||
}
|
||||
|
||||
Public.Data.surfacename_rendering_pos = {x = -0.5, y = -15}
|
||||
|
||||
function Public.get_cabin_surface_name()
|
||||
local memory = Memory.get_crew_memory()
|
||||
return SurfacesCommon.encode_surface_name(memory.id, 1, SurfacesCommon.enum.CABIN, enum.DEFAULT)
|
||||
end
|
||||
|
||||
function Public.get_cabin_surface()
|
||||
local name = Public.get_cabin_surface_name()
|
||||
if name and game.surfaces[name] and game.surfaces[name].valid then return game.surfaces[Public.get_cabin_surface_name()] end
|
||||
end
|
||||
|
||||
function Public.create_cabin_surface()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
if not Public.get_cabin_surface() then
|
||||
|
||||
local width = Public.Data.width
|
||||
local height = Public.Data.height
|
||||
local map_gen_settings = Common.default_map_gen_settings(width, height)
|
||||
|
||||
map_gen_settings.autoplace_settings.decorative.treat_missing_as_default = false
|
||||
|
||||
local cabinname = Public.get_cabin_surface_name()
|
||||
|
||||
local surface = game.create_surface(cabinname, map_gen_settings)
|
||||
surface.freeze_daytime = true
|
||||
surface.daytime = 0
|
||||
surface.show_clouds = false
|
||||
|
||||
-- more here
|
||||
|
||||
Common.ensure_chunks_at(surface, {x = 0, y = 0}, 3)
|
||||
|
||||
boat.cabin_whitebelts = {}
|
||||
for _, b in ipairs(Public.Data.cabin_whitebelts_lrtp_order) do
|
||||
local p = {x = b.x, y = b.y}
|
||||
local e = surface.create_entity({name = 'linked-belt', position = p, force = boat.force_name, create_build_effect_smoke = false, direction = b.direction})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.operable = false
|
||||
e.linked_belt_type = b.type
|
||||
boat.cabin_whitebelts[#boat.cabin_whitebelts + 1] = e
|
||||
end
|
||||
end
|
||||
|
||||
boat.cabin_splitters = {}
|
||||
for i, splitter in ipairs(Public.Data.cabin_splitters) do
|
||||
local name = 'express-splitter'
|
||||
local p = {x = splitter.x, y = splitter.y}
|
||||
local priority, filter
|
||||
if splitter.type == 0 then
|
||||
priority = 'right'
|
||||
filter = 'coal'
|
||||
elseif splitter.type <= 6 then
|
||||
priority = 'right'
|
||||
filter = game.item_prototypes[CoreData.cost_items[splitter.type].name]
|
||||
elseif splitter.type == 7 then
|
||||
priority = 'left'
|
||||
elseif splitter.type == 8 then
|
||||
priority = 'right'
|
||||
filter = 'landfill'
|
||||
end
|
||||
local e = surface.create_entity({name = name, position = p, force = boat.force_name, create_build_effect_smoke = false, direction = splitter.direction})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.operable = false
|
||||
if filter then e.splitter_filter = filter end
|
||||
if priority then e.splitter_output_priority = priority end
|
||||
boat.cabin_splitters[#boat.cabin_splitters + 1] = e
|
||||
end
|
||||
end
|
||||
|
||||
boat.input_chests = {}
|
||||
for i, b in ipairs(Public.Data.input_chests) do
|
||||
local p = {x = b.x, y = b.y}
|
||||
local e = surface.create_entity({name = 'blue-chest', position = p, force = boat.force_name, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
-- e.operable = false
|
||||
boat.input_chests[#boat.input_chests + 1] = e
|
||||
end
|
||||
end
|
||||
|
||||
local p = {x = Public.Data.output_chest.x, y = Public.Data.output_chest.y}
|
||||
local e = surface.create_entity({name = 'red-chest', position = p, force = boat.force_name, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
-- e.operable = false
|
||||
boat.output_chest = e
|
||||
end
|
||||
|
||||
p = {x = Public.Data.backup_output_chest.x, y = Public.Data.backup_output_chest.y}
|
||||
e = surface.create_entity({name = 'red-chest', position = p, force = boat.force_name, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
-- e.operable = false
|
||||
boat.backup_output_chest = e
|
||||
end
|
||||
|
||||
local es = Common.build_from_blueprint(Public.Data.static_entities_bp, surface, {x=0, y=0}, boat.force_name)
|
||||
for _, e2 in pairs(es) do
|
||||
if e2 and e2.valid then
|
||||
e2.destructible = false
|
||||
e2.minable = false
|
||||
e2.rotatable = false
|
||||
e2.operable = false
|
||||
end
|
||||
end
|
||||
local es2 = Common.build_from_blueprint(Public.Data.operable_entities_bp, surface, {x=4, y=0}, boat.force_name)
|
||||
for _, e2 in pairs(es2) do
|
||||
if e2 and e2.valid then
|
||||
e2.destructible = false
|
||||
e2.minable = false
|
||||
e2.rotatable = false
|
||||
end
|
||||
end
|
||||
e = surface.create_entity({name = 'car', position = Public.Data.car_pos, force = boat.force_name, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.get_inventory(defines.inventory.fuel).insert({name = 'wood', count = 16})
|
||||
e.color = {148, 106, 52}
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.operable = false
|
||||
end
|
||||
|
||||
rendering.draw_text{
|
||||
text = 'Captain\'s Cabin',
|
||||
surface = surface,
|
||||
target = Public.Data.surfacename_rendering_pos,
|
||||
color = CoreData.colors.renderingtext_yellow,
|
||||
scale = 3.5,
|
||||
font = 'default-game',
|
||||
alignment = 'center'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function Public.connect_up_linked_belts_to_deck() --assumes both are in standard lrtd order
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
if boat and boat.deck_whitebelts and #boat.deck_whitebelts > 0 and boat.cabin_whitebelts and #boat.cabin_whitebelts > 0 then
|
||||
|
||||
local connections = {
|
||||
{1,7},
|
||||
{2,8},
|
||||
{3,9},
|
||||
{4,10},
|
||||
{5,11},
|
||||
{6,12},
|
||||
}
|
||||
|
||||
for _, c in pairs(connections) do
|
||||
local b1 = boat.cabin_whitebelts[c[1]]
|
||||
local b2 = boat.deck_whitebelts[c[2]]
|
||||
b1.connect_linked_belts(b2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
if args.p.x > Public.Data.width/2-1 and (args.p.y > 2 or args.p.y < -2) then
|
||||
args.tiles[#args.tiles + 1] = {name = 'out-of-map', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = CoreData.static_boat_floor, position = args.p}
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Public.chunk_structures()
|
||||
return nil
|
||||
end
|
||||
|
||||
return Public
|
33
maps/pirates/surfaces/channel/channel.lua
Normal file
33
maps/pirates/surfaces/channel/channel.lua
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
-- local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.channel.data'
|
||||
|
||||
Public.info = {
|
||||
display_name = 'Channel'
|
||||
}
|
||||
|
||||
function Public.terrain(args)
|
||||
|
||||
if (args.p.y>30 or args.p.y<-20) and args.p.x>-80 and args.p.x<80 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'deepwater', position = args.p}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function Public.chunk_structures()
|
||||
return nil
|
||||
end
|
||||
|
||||
return Public
|
16
maps/pirates/surfaces/channel/data.lua
Normal file
16
maps/pirates/surfaces/channel/data.lua
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.width = 384
|
||||
Public.height = 384
|
||||
Public.extra_water_on_left = 96
|
||||
|
||||
Public.noiseparams = {
|
||||
}
|
||||
|
||||
|
||||
|
||||
return Public
|
67
maps/pirates/surfaces/common.lua
Normal file
67
maps/pirates/surfaces/common.lua
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
-- 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 Public = {}
|
||||
local enum = {
|
||||
SEA = 'Sea',
|
||||
ISLAND = 'Island',
|
||||
CROWSNEST = 'Crowsnest',
|
||||
LOBBY = 'Lobby',
|
||||
HOLD = 'Hold',
|
||||
CABIN = 'Cabin',
|
||||
CHANNEL = 'Channel',
|
||||
DOCK = 'Dock',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
|
||||
function Public.encode_surface_name(crewid, destination_index, type, subtype) -- crewid=0 is shared surfaces
|
||||
local str
|
||||
if subtype then
|
||||
str = string.format('%03d-%03d-%s-%s', crewid, destination_index, type, subtype) --uses the fact that type and subtype resolve to strings
|
||||
else
|
||||
str = string.format('%03d-%03d-%s', crewid, destination_index, type)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
function Public.decode_surface_name(name)
|
||||
local crewid = tonumber(string.sub(name, 1, 3))
|
||||
local destination_index = tonumber(string.sub(name, 5, 7))
|
||||
local type = nil
|
||||
local subtype = nil
|
||||
|
||||
local substring = string.sub(name, 9, -1)
|
||||
local pull = {}
|
||||
for a, b in string.gmatch(substring, "(%w+)-(%w+)") do
|
||||
pull[1] = a
|
||||
pull[2] = b
|
||||
end
|
||||
if #pull == 0 then
|
||||
type = substring
|
||||
elseif #pull == 2 then
|
||||
type = pull[1]
|
||||
subtype = pull[2]
|
||||
end
|
||||
return {crewid = crewid, destination_index = destination_index, type = type, subtype = subtype}
|
||||
end
|
||||
|
||||
function Public.fetch_iconized_map(destination)
|
||||
local type = destination.type
|
||||
|
||||
if type == Public.enum.LOBBY then
|
||||
return CoreData.Lobby_iconized_map()
|
||||
elseif type == Public.enum.DOCK then
|
||||
return CoreData.Dock_iconized_map()
|
||||
else
|
||||
return destination.iconized_map
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
429
maps/pirates/surfaces/crowsnest.lua
Normal file
429
maps/pirates/surfaces/crowsnest.lua
Normal file
@ -0,0 +1,429 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
-- 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 Math = require 'maps.pirates.math'
|
||||
local CustomEvents = require 'maps.pirates.custom_events'
|
||||
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Token = require 'utils.token'
|
||||
local Task = require 'utils.task'
|
||||
|
||||
local SurfacesCommon = require 'maps.pirates.surfaces.common'
|
||||
|
||||
-- This file is logically a bit of a mess, because we changed from islands moving to the crowsnest platform moving.
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
DEFAULT = 'Default',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
Public.Data = {}
|
||||
Public.Data.chartingdistance = 130
|
||||
Public.Data.visibilitywidth = 400
|
||||
Public.Data.width = 10000 --minimap won't chart beyond this point
|
||||
Public.Data.height = 72
|
||||
Public.platformwidth = 7
|
||||
Public.platformheight = 7
|
||||
Public.platformrightmostedge = 4
|
||||
|
||||
Public.Data.chestspos = {
|
||||
{x = -2.5, y = -3.5},
|
||||
{x = -1.5, y = -3.5},
|
||||
{x = -0.5, y = -3.5},
|
||||
{x = 1.5, y = -3.5},
|
||||
{x = 2.5, y = -3.5},
|
||||
{x = 3.5, y = -3.5},
|
||||
{x = -2.5, y = 3.5},
|
||||
{x = -1.5, y = 3.5},
|
||||
{x = -0.5, y = 3.5},
|
||||
{x = 1.5, y = 3.5},
|
||||
{x = 2.5, y = 3.5},
|
||||
{x = 3.5, y = 3.5},
|
||||
{x = -2.5, y = -2.5},
|
||||
{x = -2.5, y = -1.5},
|
||||
{x = -2.5, y = 1.5},
|
||||
{x = -2.5, y = 2.5},
|
||||
{x = 3.5, y = -2.5},
|
||||
{x = 3.5, y = -1.5},
|
||||
{x = 3.5, y = 1.5},
|
||||
{x = 3.5, y = 2.5},
|
||||
}
|
||||
|
||||
Public.Data.surfacename_rendering_pos = {x = 0.5, y = -6.1}
|
||||
|
||||
function Public.crowsnest_surface_name()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
return SurfacesCommon.encode_surface_name(memory.id, 0, SurfacesCommon.enum.CROWSNEST, nil)
|
||||
end
|
||||
|
||||
function Public.get_crowsnest_surface()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
return game.surfaces[Public.crowsnest_surface_name()]
|
||||
end
|
||||
|
||||
|
||||
function Public.move_crowsnest(vectorx, vectory)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
|
||||
local old_area = {{memory.overworldx - 2.5, memory.overworldy - 3.5},{memory.overworldx + 3.5, memory.overworldy + 3.5}}
|
||||
|
||||
memory.overworldx = memory.overworldx + vectorx
|
||||
memory.overworldy = memory.overworldy + vectory
|
||||
|
||||
local new_area = {{memory.overworldx - 2.5, memory.overworldy - 3.5},{memory.overworldx + 3.5, memory.overworldy + 3.5}}
|
||||
|
||||
local new_floor_positions = {}
|
||||
local tiles1 = {}
|
||||
for y = new_area[1][2], new_area[2][2], 1 do
|
||||
for x = new_area[1][1], new_area[2][1], 1 do
|
||||
if not new_floor_positions[x] then new_floor_positions[x] = {} end
|
||||
new_floor_positions[x][y] = true
|
||||
tiles1[#tiles1 + 1] = {name = CoreData.static_boat_floor, position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles1, true, true, true)
|
||||
|
||||
local entities_to_teleport = surface.find_entities_filtered{area = old_area}
|
||||
for _, e in pairs(entities_to_teleport) do
|
||||
e.teleport(vectorx, vectory)
|
||||
end
|
||||
|
||||
local tiles2 = {}
|
||||
for y = old_area[1][2], old_area[2][2], 1 do
|
||||
for x = old_area[1][1], old_area[2][1], 1 do
|
||||
if not (new_floor_positions[x] and new_floor_positions[x][y]) then
|
||||
tiles2[#tiles2 + 1] = {name = 'deepwater', position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles2, true, true, true)
|
||||
|
||||
if memory.crowsnest_surfacename_rendering then
|
||||
local p = rendering.get_target(memory.crowsnest_surfacename_rendering).position
|
||||
rendering.set_target(memory.crowsnest_surfacename_rendering, {x = p.x + vectorx, y = p.y + vectory})
|
||||
end
|
||||
|
||||
if vectorx ~= 0 then
|
||||
local crew_force = memory.force
|
||||
local area = {{memory.overworldx,-Public.Data.height/2},{memory.overworldx+Public.Data.chartingdistance,Public.Data.height/2}}
|
||||
-- crew_force.clear_chart(surface)
|
||||
crew_force.chart(surface, area)
|
||||
end
|
||||
|
||||
script.raise_event(CustomEvents.enum['update_crew_progress_gui'], {})
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.update_destination_renderings()
|
||||
local memory = Memory.get_crew_memory()
|
||||
for _, dest in pairs(memory.destinations) do
|
||||
if dest.dynamic_data.crowsnest_renderings then
|
||||
if dest.overworld_position.x <= memory.overworldx+Public.Data.chartingdistance and dest.overworld_position.x >= memory.overworldx-Public.Data.chartingdistance then
|
||||
for _, r in pairs(dest.dynamic_data.crowsnest_renderings) do
|
||||
if type(r) == 'table' then
|
||||
if rendering.is_valid(r.text_rendering) then
|
||||
rendering.set_visible(r.text_rendering, true)
|
||||
end
|
||||
if rendering.is_valid(r.sprite_rendering) then
|
||||
rendering.set_visible(r.sprite_rendering, true)
|
||||
end
|
||||
else
|
||||
if rendering.is_valid(r) then
|
||||
rendering.set_visible(r, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for _, r in pairs(dest.dynamic_data.crowsnest_renderings) do
|
||||
if type(r) == 'table' then
|
||||
if rendering.is_valid(r.text_rendering) then
|
||||
rendering.set_visible(r.text_rendering, false)
|
||||
end
|
||||
if rendering.is_valid(r.sprite_rendering) then
|
||||
rendering.set_visible(r.sprite_rendering, false)
|
||||
end
|
||||
else
|
||||
if rendering.is_valid(r) then
|
||||
rendering.set_visible(r, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.draw_kraken(p)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
|
||||
surface.set_tiles({{name = CoreData.kraken_tile, position = {x = Public.platformrightmostedge + p.x, y = p.y}}}, true, true, true)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.draw_destination(destination)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
|
||||
local tiles = {}
|
||||
-- local entities = {}
|
||||
-- local renderings = {}
|
||||
|
||||
local iconized_map = SurfacesCommon.fetch_iconized_map(destination)
|
||||
|
||||
if not iconized_map then iconized_map = destination.iconized_map end
|
||||
|
||||
local x = Public.platformrightmostedge + destination.overworld_position.x
|
||||
local y = destination.overworld_position.y
|
||||
|
||||
for _, t in pairs(iconized_map.tiles) do
|
||||
local t2 = Utils.deepcopy(t)
|
||||
t2.position = {x = x + t.position.x, y = y + t.position.y}
|
||||
tiles[#tiles+1] = t2
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles, true, true, true)
|
||||
|
||||
for _, e in pairs(iconized_map.entities) do
|
||||
local e2 = Utils.deepcopy(e)
|
||||
e2.position = {x = x + e.position.x, y = y + e.position.y}
|
||||
if e2.source then e2.source = {x = e2.source.x + x, y = e2.source.y + y} end
|
||||
if e2.target then e2.target = {x = e2.target.x + x, y = e2.target.y + y} end
|
||||
surface.create_entity(e2)
|
||||
end
|
||||
|
||||
-- Now we can destroy the iconized_map... right?
|
||||
destination.iconized_map = nil
|
||||
end
|
||||
|
||||
function Public.draw_extra_bits()
|
||||
Public.draw_destination{
|
||||
type = 'finish line',
|
||||
seed = 0,
|
||||
overworld_position = {x = CoreData.victory_x, y = 0},
|
||||
static_params = {},
|
||||
dynamic_data = {},
|
||||
iconized_map = {
|
||||
tiles = {},
|
||||
entities = {
|
||||
{name = 'electric-beam', position = {x = 0, y = 0}, source = {x = 0, y = -37}, target = {x = 0, y = 37}},
|
||||
{name = 'electric-beam', position = {x = 0, y = 0}, source = {x = 0, y = -37}, target = {x = 0, y = 37}},
|
||||
},
|
||||
},
|
||||
iconized_map_width = 2,
|
||||
iconized_map_height = 2,
|
||||
}
|
||||
|
||||
Public.draw_destination{
|
||||
type = 'Lobby',
|
||||
overworld_position = {x = -14, y = 0},
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.create_crowsnest_surface()
|
||||
-- if not game.surfaces[crowsnest_surface_name()] then
|
||||
local memory = Memory.get_crew_memory()
|
||||
local map_gen_settings = Common.default_map_gen_settings(Public.Data.width, Public.Data.height)
|
||||
|
||||
game.create_surface(Public.crowsnest_surface_name(), map_gen_settings)
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
surface.freeze_daytime = true
|
||||
surface.daytime = 0
|
||||
|
||||
Common.ensure_chunks_at(surface, {x = 0, y = 0}, 15)
|
||||
|
||||
Public.paint_crowsnest_background_tiles()
|
||||
-- end
|
||||
|
||||
memory.crowsnest_surfacename_rendering = rendering.draw_text{
|
||||
text = 'Crow\'s Nest',
|
||||
surface = surface,
|
||||
target = Public.Data.surfacename_rendering_pos,
|
||||
color = CoreData.colors.renderingtext_yellow,
|
||||
scale = 2.5,
|
||||
font = 'default-game',
|
||||
alignment = 'center'
|
||||
}
|
||||
end
|
||||
|
||||
function Public.paint_water_between_overworld_positions(overworldx1, overworldx2)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
|
||||
Common.ensure_chunks_at(surface, {x = overworldx2, y = 0}, 10)
|
||||
|
||||
local tiles = {}
|
||||
for y = -(Public.Data.height+32 - 1)/2, (Public.Data.height+32 - 1)/2, 1 do
|
||||
for x = Public.platformrightmostedge + overworldx1, Public.platformrightmostedge + overworldx2 do
|
||||
if y>= -(Public.Data.height - 1)/2 and y <= (Public.Data.height - 1)/2 then
|
||||
tiles[#tiles + 1] = {name = 'deepwater', position = {x = x, y = y}}
|
||||
else
|
||||
tiles[#tiles + 1] = {name = 'out-of-map', position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles)
|
||||
end
|
||||
|
||||
function Public.paint_crowsnest_background_tiles()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
|
||||
local tiles = {}
|
||||
for y = -(Public.Data.height+32 - 1)/2, (Public.Data.height+32 - 1)/2, 1 do
|
||||
for x = -(Public.Data.visibilitywidth+32 - 1)/2, (Public.Data.visibilitywidth+32 - 1)/2, 1 do
|
||||
if x <= 3.5 and x >= -2.5 and y <= 3.5 and y >= -3.5 then
|
||||
tiles[#tiles + 1] = {name = CoreData.static_boat_floor, position = {x = x, y = y}}
|
||||
elseif x>= -(Public.Data.visibilitywidth - 1)/2 and x <= (Public.Data.visibilitywidth - 1)/2 and y>= -(Public.Data.height - 1)/2 and y <= (Public.Data.height - 1)/2 then
|
||||
tiles[#tiles + 1] = {name = 'deepwater', position = {x = x, y = y}}
|
||||
else
|
||||
tiles[#tiles + 1] = {name = 'out-of-map', position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles)
|
||||
end
|
||||
|
||||
|
||||
function Public.upgrade_chests(new_chest) --the fast replace doesn't work well on the '/go' tick, but that's okay
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
local surface = Public.get_crowsnest_surface()
|
||||
local ps = Public.Data.chestspos
|
||||
|
||||
for _, p in pairs(ps) do
|
||||
local p2 = {x = p.x + memory.overworldx, y = p.y + memory.overworldy}
|
||||
local es = surface.find_entities_filtered{name = 'wooden-chest', position = p2, radius = 0.05}
|
||||
if es and #es == 1 then
|
||||
es[1].minable = true
|
||||
es[1].destructible = true
|
||||
es[1].rotatable = true
|
||||
-- es[1].operable = true
|
||||
local e2 = surface.create_entity{name = new_chest, position = es[1].position, fast_replace = true, spill = false, force = boat.force_name}
|
||||
e2.minable = false
|
||||
e2.destructible = false
|
||||
e2.rotatable = false
|
||||
-- e2.operable = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- just for debug purposes, might need to fire this again
|
||||
local crowsnest_delayed = Token.register(
|
||||
function(data)
|
||||
Memory.set_working_id(data.crew_id)
|
||||
Public.crowsnest_surface_delayed_init()
|
||||
end
|
||||
)
|
||||
|
||||
function Public.crowsnest_surface_delayed_init()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
local force = memory.force
|
||||
|
||||
if _DEBUG and (not (surface and surface.valid)) then
|
||||
game.print('/go issue: crowsnest_surface_delayed_init called when crowsnest surface wasn\'t valid. This happens due to a difficult-to-handle race condition in concurrent delayed events in the /go shortcut. Firing event again...')
|
||||
Task.set_timeout_in_ticks(5, crowsnest_delayed, {crew_id = memory.id})
|
||||
return
|
||||
end
|
||||
|
||||
surface.destroy_decoratives{area = {{-3, -4},{4, 4}}}
|
||||
|
||||
local chestspos = Public.Data.chestspos
|
||||
local steerchestspos = {
|
||||
{x = 0.5, y = -3.5},
|
||||
{x = 0.5, y = 3.5},
|
||||
}
|
||||
local carspos = {
|
||||
{x = 3.3, y = 0},
|
||||
{x = -2.3, y = 0},
|
||||
}
|
||||
for _, p in pairs(chestspos) do
|
||||
local e = surface.create_entity({name = 'wooden-chest', position = p, force = force, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
end
|
||||
end
|
||||
for _, p in pairs(steerchestspos) do
|
||||
local e = surface.create_entity({name = 'blue-chest', position = p, force = force, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
if not memory.boat.crowsneststeeringchests then
|
||||
memory.boat.crowsneststeeringchests = {}
|
||||
end
|
||||
if p.y < 0 then
|
||||
memory.boat.crowsneststeeringchests.left = e
|
||||
else
|
||||
memory.boat.crowsneststeeringchests.right = e
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, p in pairs(carspos) do
|
||||
local e = surface.create_entity({name = 'car', position = p, force = force, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.get_inventory(defines.inventory.fuel).insert({name = 'wood', count = 16})
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.operable = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.paint_around_destination(id, tile_name)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination_data = memory.destinations[id]
|
||||
local surface = game.surfaces[Public.crowsnest_surface_name()]
|
||||
|
||||
-- local static_params = destination_data.static_params
|
||||
local type = destination_data.type
|
||||
|
||||
local tiles = {}
|
||||
if type == SurfacesCommon.enum.ISLAND then
|
||||
|
||||
for x = memory.overworldx + Public.platformrightmostedge + 0.5, memory.overworldx + Public.platformrightmostedge + destination_data.iconized_map_width - 0.5 do
|
||||
tiles[#tiles+1] = {name = tile_name, position = {x = x, y = memory.overworldy + destination_data.iconized_map_height/2 - 0.5}}
|
||||
tiles[#tiles+1] = {name = tile_name, position = {x = x, y = memory.overworldy - destination_data.iconized_map_height/2 + 0.5}}
|
||||
end
|
||||
for y = memory.overworldy + -destination_data.iconized_map_height/2 + 1.5, memory.overworldy + destination_data.iconized_map_height/2 - 1.5 do
|
||||
tiles[#tiles+1] = {name = tile_name, position = {x = memory.overworldx + Public.platformrightmostedge + 0.5, y = y}}
|
||||
tiles[#tiles+1] = {name = tile_name, position = {x = memory.overworldx + Public.platformrightmostedge + destination_data.iconized_map_width - 0.5, y = y}}
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles, true, true, true)
|
||||
end
|
||||
|
||||
function Public.terrain() --blank since we do this manually
|
||||
--
|
||||
end
|
||||
|
||||
function Public.chunk_structures()
|
||||
--
|
||||
end
|
||||
|
||||
return Public
|
||||
|
160
maps/pirates/surfaces/dock.lua
Normal file
160
maps/pirates/surfaces/dock.lua
Normal file
File diff suppressed because one or more lines are too long
375
maps/pirates/surfaces/hold.lua
Normal file
375
maps/pirates/surfaces/hold.lua
Normal file
@ -0,0 +1,375 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
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 SurfacesCommon = require 'maps.pirates.surfaces.common'
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
INITIAL = 'Initial',
|
||||
SECONDARY = 'Secondary',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
Public.Data = {}
|
||||
|
||||
-- local enum_boat = Boats.enum
|
||||
-- Public.enum_boat = enum_boat
|
||||
|
||||
Public.Data.width = 92
|
||||
Public.Data.height = 46
|
||||
Public.Data.loco_offset = {x = -2, y = 0}
|
||||
-- Public.Data.loco_offset = {x = 18, y = 0}
|
||||
-- Public.Data.display_name = 'Ship\'s Hold'
|
||||
Public.Data.downstairs_pole_positions = {
|
||||
{x = -1, y = -5},
|
||||
{x = -1, y = 5},
|
||||
}
|
||||
|
||||
Public[enum.INITIAL] = {}
|
||||
Public[enum.INITIAL].Data = {}
|
||||
Public[enum.INITIAL].Data.hold_whitebelts_lrtp_order = {
|
||||
{x = -19.5, y = -21.5, direction = defines.direction.north, type = 'output'},
|
||||
{x = -18.5, y = -21.5, direction = defines.direction.north, type = 'output'},
|
||||
{x = -17.5, y = -21.5, direction = defines.direction.north, type = 'output'},
|
||||
|
||||
{x = 17.5, y = -21.5, direction = defines.direction.north, type = 'output'},
|
||||
{x = 18.5, y = -21.5, direction = defines.direction.north, type = 'output'},
|
||||
{x = 19.5, y = -21.5, direction = defines.direction.north, type = 'output'},
|
||||
|
||||
{x = -44.5, y = -3.5, direction = defines.direction.west, type = 'output'},
|
||||
{x = 44.5, y = -3.5, direction = defines.direction.east, type = 'output'},
|
||||
{x = -44.5, y = -2.5, direction = defines.direction.west, type = 'output'},
|
||||
{x = 44.5, y = -2.5, direction = defines.direction.east, type = 'output'},
|
||||
{x = -44.5, y = 2.5, direction = defines.direction.west, type = 'input'},
|
||||
{x = 44.5, y = 2.5, direction = defines.direction.east, type = 'input'},
|
||||
{x = -44.5, y = 3.5, direction = defines.direction.west, type = 'input'},
|
||||
{x = 44.5, y = 3.5, direction = defines.direction.east, type = 'input'},
|
||||
|
||||
{x = -19.5, y = 21.5, direction = defines.direction.south, type = 'input'},
|
||||
{x = -18.5, y = 21.5, direction = defines.direction.south, type = 'input'},
|
||||
{x = -17.5, y = 21.5, direction = defines.direction.south, type = 'input'},
|
||||
|
||||
{x = 17.5, y = 21.5, direction = defines.direction.south, type = 'input'},
|
||||
{x = 18.5, y = 21.5, direction = defines.direction.south, type = 'input'},
|
||||
{x = 19.5, y = 21.5, direction = defines.direction.south, type = 'input'},
|
||||
}
|
||||
|
||||
Public[enum.SECONDARY] = {}
|
||||
Public[enum.SECONDARY].Data = {}
|
||||
Public[enum.SECONDARY].Data.hold_whitebelts_lrtp_order = {
|
||||
{x = -44.5, y = -3.5, direction = defines.direction.west, type = 'output'},
|
||||
{x = 44.5, y = -3.5, direction = defines.direction.east, type = 'output'},
|
||||
{x = -44.5, y = -2.5, direction = defines.direction.west, type = 'output'},
|
||||
{x = 44.5, y = -2.5, direction = defines.direction.east, type = 'output'},
|
||||
{x = -44.5, y = 2.5, direction = defines.direction.west, type = 'input'},
|
||||
{x = 44.5, y = 2.5, direction = defines.direction.east, type = 'input'},
|
||||
{x = -44.5, y = 3.5, direction = defines.direction.west, type = 'input'},
|
||||
{x = 44.5, y = 3.5, direction = defines.direction.east, type = 'input'},
|
||||
}
|
||||
|
||||
Public.Data.boxes_bp = [[0eNqV3OtqI0cUBOB3md/you5z+jJ6lbAE71psBGvJWNokZtG7x5cQAkmpqn4a7GJafDrTmlL75/Ll+4/90/PheFl2P5fz8f7p7nK6+/Z8eHj7+c9lt9bN8rLssl83y+Hr6Xhedr+8/uLh2/H++9uvXF6e9stuOVz2j8tmOd4/vv30x+n0sD/eff1tf74sb394fNi/ZpXr582yP14Ol8P+I+f9h5dfjz8ev+yfX3/h/xM2y9Pp/PpHp+PfF1U+tfer2n5q1+vmPzFVjNnejgkxJm7HpBhTb8c0MSZvx3Qxpt2OGWJMvx0zxZhxO2YVY+btmLIVc1aSIzsmAosquZB3RFEtF6KwqJoLeVcU1XMhoIsquhDSRTVdCOqiqi6EdVFdFwK7qrALkV1V2ZXIrqrsyma9KrsS2VWe00R2VWVXIruqsiuRXVXZlciuquxKZFdVdiWyQ5VdiexQZQfbNaiyg8gOef9BZIcqO4jsUGUHkR2q7CCyQ5UdRHaosoPIDlV2ENmpyg4iO1XZSWSnKjuJ7FRlJ5Gdquxke3R5d01kpyo7iexUZSeRnarsJLJTlZ1EdlNlJ5HdVNmNyG6q7EZkN1V2Y5/2VNmNyG6q7EZkN/mTI5HdVNmNyG6q7EZkN1V2I7K7KrsR2V2V3YnsrsruRHZXZXciu6uyO5HdVdmdPRJRZXciu8tPRYjsrsruRHZXZXcie6iyO5E9VNmDyB6q7EFkD1X2ILKHKnsQ2UOVPYjsocoe7HGfKnsQ2UN+4kdkD1X2ILKnKnsQ2VOVPYnsqcqeRPZUZU8ie6qyJ5E9VdmTyJ6q7ElkT1X2ZI+yVdmTyJ7y02wie1VlTyJ7VWWvRPaqyl6J7DXMiqeCnDRzCshp7sLQBXU3CF3RMFeWIGeaOQFyVndhiUqarZsUKKmYa+soyG0cGwoKd23wktJNgtfUzMVNFNTNoIGChrs2mDTdJLi41Z0ksDzcmkkrCiru4mCSPbfx6tzJXSpKsmd3QUn29MZR/vyG63MneEETs7gzvKCJWewpDqOqPcbh+qo7xwuamtUd5AVNzWpPchxlj3K8PneWFzTvqjvMC5rB1Z7mOMoe53h97jyv8KsX7jwvaAzLHeU/5QKOqm7hgaN86TDKlo5fdVd6RXM4XOkV3RzClo6jbOl4fbZ0NIfTlV7RzSHtrQuOsvcueH32p040h9Pdu1R0c9Cby0YvqrszAUf50uECfenwqmzp6O7QbOnoltV86TDKlw7X50oP+DU/Wzq6OTT/GQuMsnfpeH3uLj3QHG72kxZ0c2j2Lh1Gdf9hC1pfd3fpgeZwd3fpgW4O3d674Ch774LX5+5dAk287u5dAo3hbk90HGVPdLw+d6IHmnjDneiBxvCwJzq+KHui46tyJ3rCr0m7Ez3QGB72RMcX5U90eFX2k3M08YY70RON4eE/PUdR057ocH3TneiJJt50J3qiMTztiY6j7ImO19fMk02Jhud0JzpOGub5Jpw0zSNOOGk1jyfBJLn8TJpUzENKOKmap6ZwUpgnlXBSmmencFJzDyvhqO4eoMJRwz2whKOme4gKR63uoSUUVeU6tCSNKu7BJRxV3cNUOCrcw0s4Kt0DVTiquQeYcFR3D1XhqOEeYsJR0z1YhaNW9yATjJLL0Uq1y/VopdrlfrRS7XI/Wql2uSCtVLvckAbVLjekQbXLDWlQ7XJFGlS73JEG1S53pEG1yx1pUO1ySRpUu9ySBtUut6RBtcstaVLtck2aVLvckybVLvekSbXLPWlS7XJRmlS73pRS7XpTSrXLTWlS7XJTmlS73JQ2ql2uShvVLneljWqXu9JGtctdaaPa5bK0Ue1yW9qodrktbVS73JY2ql2uSxvVLvelnWqX+9JOtct9aafa5b60U+1yX9qpdrkw7VS73Jh2ql1uTDvVLjemnWqXK9NOtcud6aDa5c50UO1yZzqodrk0HVS73JoOql1uTQfVLremgxKVa9NB3zhybzooUbk3HfSNI/emkxKVi9NJ3zhyczr5yz7dEz04yj5lBKPk6nSlL7vfnX5Efd58/Ae63b/+n91m+X3/fH7/kzpLjrWOjJ5rndfrX67iTLU=]]
|
||||
Public.Data.boxes_bp_offset = {x = 0, y = 0}
|
||||
|
||||
Public.Data.surfacename_rendering_pos = {x = Public.Data.loco_offset.x, y = -Public.Data.height/2 - 5}
|
||||
|
||||
function Public.get_hold_surface_name(nth)
|
||||
nth = nth or 1
|
||||
local memory = Memory.get_crew_memory()
|
||||
local subtype = (nth == 1) and enum.INITIAL or enum.SECONDARY
|
||||
return SurfacesCommon.encode_surface_name(memory.id, nth, SurfacesCommon.enum.HOLD, subtype)
|
||||
end
|
||||
|
||||
function Public.get_hold_surface(nth)
|
||||
nth = nth or 1
|
||||
local name = Public.get_hold_surface_name(nth)
|
||||
if name and game.surfaces[name] and game.surfaces[name].valid then return game.surfaces[name] end
|
||||
end
|
||||
|
||||
function Public.create_hold_surface(nth)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
|
||||
local width = Public.Data.width
|
||||
local height = Public.Data.height
|
||||
local map_gen_settings = Common.default_map_gen_settings(width, height)
|
||||
|
||||
map_gen_settings.autoplace_settings.decorative.treat_missing_as_default = false
|
||||
|
||||
local holdname = Public.get_hold_surface_name(nth)
|
||||
|
||||
if not holdname then log(_inspect{'holdname is nil? here some stuff:', memory.id, nth, SurfacesCommon.enum.HOLD}) end
|
||||
|
||||
local surface = game.create_surface(holdname, map_gen_settings)
|
||||
surface.freeze_daytime = true
|
||||
surface.daytime = 0
|
||||
surface.show_clouds = false
|
||||
surface.solar_power_multiplier = 0
|
||||
|
||||
-- more here
|
||||
|
||||
Common.ensure_chunks_at(surface, {x = 0, y = 0}, 5)
|
||||
|
||||
|
||||
local subtype = nth == 1 and enum.INITIAL or enum.SECONDARY
|
||||
|
||||
local whitebelts_table, whitebelts_data
|
||||
|
||||
if (not boat.hold_whitebelts) then boat.hold_whitebelts = {} end
|
||||
boat.hold_whitebelts[nth] = {}
|
||||
whitebelts_table = boat.hold_whitebelts[nth]
|
||||
|
||||
if subtype == enum.INITIAL then
|
||||
whitebelts_data = Public[enum.INITIAL].Data.hold_whitebelts_lrtp_order
|
||||
elseif subtype == enum.SECONDARY then
|
||||
whitebelts_data = Public[enum.SECONDARY].Data.hold_whitebelts_lrtp_order
|
||||
end
|
||||
|
||||
for _, b in ipairs(whitebelts_data) do
|
||||
local p = {x = b.x, y = b.y}
|
||||
local e = surface.create_entity({name = 'linked-belt', position = p, force = boat.force_name, create_build_effect_smoke = false, direction = b.direction})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
e.operable = false
|
||||
local type = b.type
|
||||
if nth % 2 == 0 then
|
||||
if type == 'input' then type = 'output' else type = 'input' end
|
||||
end
|
||||
e.linked_belt_type = type
|
||||
whitebelts_table[#whitebelts_table + 1] = e
|
||||
end
|
||||
end
|
||||
|
||||
local boxes = Common.build_from_blueprint(Public.Data.boxes_bp, surface, Public.Data.boxes_bp_offset, boat.force_name)
|
||||
for _, e in pairs(boxes) do
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
end
|
||||
end
|
||||
|
||||
Common.build_small_loco(surface, Public.Data.loco_offset, memory.force, {255, 106, 52})
|
||||
|
||||
local items = subtype == enum.INITIAL and Balance.starting_items_crew_downstairs() or {}
|
||||
Common.surface_place_random_obstacle_boxes(Public.get_hold_surface(nth), {x=0,y=0}, Public.Data.width, Public.Data.height, 'rocket-silo', {[1] = 0, [2] = 5, [3] = 4, [4] = 2}, items)
|
||||
-- Public.hold_place_random_obstacle_boxes(nth, {[1] = 0, [2] = 9, [3] = 3, [4] = 1}, items)
|
||||
|
||||
if not boat.downstairs_poles then boat.downstairs_poles = {} end
|
||||
boat.downstairs_poles[nth] = {}
|
||||
for i = 1, 2 do
|
||||
local e = surface.create_entity({name = 'substation', position = Public.Data.downstairs_pole_positions[i], force = boat.force_name, create_build_effect_smoke = false})
|
||||
if e and e.valid then
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.rotatable = false
|
||||
boat.downstairs_poles[nth][i] = e
|
||||
end
|
||||
end
|
||||
if nth >= 2 then
|
||||
if boat.downstairs_poles[nth][1] and boat.downstairs_poles[nth][1].valid and boat.downstairs_poles[nth-1][2] and boat.downstairs_poles[nth-1][2].valid then
|
||||
boat.downstairs_poles[nth][1].connect_neighbour(boat.downstairs_poles[nth-1][2])
|
||||
end
|
||||
end
|
||||
|
||||
if subtype == enum.SECONDARY then
|
||||
local difficulty_name = CoreData.get_difficulty_name_from_value(Common.difficulty())
|
||||
if difficulty_name == CoreData.difficulty_options[#CoreData.difficulty_options].text then
|
||||
Public.upgrade_chests(nth, 'steel-chest')
|
||||
elseif difficulty_name ~= CoreData.difficulty_options[1].text then
|
||||
Public.upgrade_chests(nth, 'iron-chest')
|
||||
end
|
||||
|
||||
Public.nth_hold_connect_linked_belts(nth)
|
||||
end
|
||||
|
||||
if nth==1 then
|
||||
memory.shiphold_rendering_1 = rendering.draw_text{
|
||||
text = 'Ship\'s Hold',
|
||||
surface = surface,
|
||||
target = Public.Data.surfacename_rendering_pos,
|
||||
color = CoreData.colors.renderingtext_yellow,
|
||||
scale = 6,
|
||||
font = 'default-game',
|
||||
alignment = 'center'
|
||||
}
|
||||
else
|
||||
if nth==2 then
|
||||
if memory.shiphold_rendering_1 then
|
||||
rendering.set_text(memory.shiphold_rendering_1, 'Ship\'s Hold: -1')
|
||||
end
|
||||
end
|
||||
rendering.draw_text{
|
||||
text = 'Ship\'s Hold: -' .. nth,
|
||||
surface = surface,
|
||||
target = Public.Data.surfacename_rendering_pos,
|
||||
color = CoreData.colors.renderingtext_yellow,
|
||||
scale = 6,
|
||||
font = 'default-game',
|
||||
alignment = 'center'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.add_another_hold_surface()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
memory.hold_surface_count = memory.hold_surface_count + 1
|
||||
|
||||
Public.create_hold_surface(memory.hold_surface_count)
|
||||
|
||||
return memory.hold_surface_count
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.upgrade_chests(nth, new_chest)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
local surface = Public.get_hold_surface(nth)
|
||||
|
||||
local ps = Common.entity_positions_from_blueprint(Public.Data.boxes_bp, {x = -Public.Data.width/2 ,y = -Public.Data.height/2})
|
||||
|
||||
for _, p in pairs(ps) do
|
||||
local es = surface.find_entities_filtered{name = 'wooden-chest', position = p, radius = 0.05}
|
||||
if es and #es == 1 then
|
||||
es[1].minable = true
|
||||
es[1].destructible = true
|
||||
es[1].rotatable = true
|
||||
end
|
||||
local e2 = surface.create_entity{name = new_chest, position = p, fast_replace = true, spill = false, force = boat.force_name}
|
||||
e2.minable = false
|
||||
e2.destructible = false
|
||||
e2.rotatable = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.connect_up_linked_belts_to_deck() --assumes both are in standard lrtd order
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
if boat and boat.deck_whitebelts and #boat.deck_whitebelts > 0 and boat.hold_whitebelts and boat.hold_whitebelts[1] and #boat.hold_whitebelts[1] > 0 then
|
||||
|
||||
local connections = {
|
||||
{1,1},
|
||||
{2,2},
|
||||
{3,3},
|
||||
{4,4},
|
||||
{5,5},
|
||||
{6,6},
|
||||
{15,13},
|
||||
{16,14},
|
||||
{17,15},
|
||||
{18,16},
|
||||
{19,17},
|
||||
{20,18},
|
||||
}
|
||||
|
||||
for _, c in pairs(connections) do
|
||||
local b1 = boat.hold_whitebelts[1][c[1]]
|
||||
local b2 = boat.deck_whitebelts[c[2]]
|
||||
b1.connect_linked_belts(b2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.nth_hold_connect_linked_belts(nth) --assumes both are in standard lrtd order
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
if boat.hold_whitebelts and boat.hold_whitebelts[nth-1] and #boat.hold_whitebelts[nth-1] > 0 and boat.hold_whitebelts[nth] and #boat.hold_whitebelts[nth] > 0 then
|
||||
|
||||
local connections
|
||||
if nth % 2 == 0 then
|
||||
if nth == 2 then
|
||||
connections = {
|
||||
{5,11},
|
||||
{6,12},
|
||||
{7,13},
|
||||
{8,14},
|
||||
}
|
||||
for _, c in pairs(connections) do
|
||||
local b1 = boat.hold_whitebelts[nth][c[1]]
|
||||
local b2 = boat.hold_whitebelts[nth-1][c[2]]
|
||||
b1.connect_linked_belts(b2)
|
||||
end
|
||||
else
|
||||
connections = {
|
||||
{5,5},
|
||||
{6,6},
|
||||
{7,7},
|
||||
{8,8},
|
||||
}
|
||||
for _, c in pairs(connections) do
|
||||
local b1 = boat.hold_whitebelts[nth][c[1]]
|
||||
local b2 = boat.hold_whitebelts[nth-1][c[2]]
|
||||
b1.connect_linked_belts(b2)
|
||||
end
|
||||
end
|
||||
connections = {
|
||||
{1,7},
|
||||
{2,8},
|
||||
{3,9},
|
||||
{4,10},
|
||||
}
|
||||
for _, c in pairs(connections) do
|
||||
local b1 = boat.hold_whitebelts[nth][c[1]]
|
||||
local b2 = boat.hold_whitebelts[1][c[2]]
|
||||
b1.connect_linked_belts(b2)
|
||||
end
|
||||
else
|
||||
connections = {
|
||||
{1,1},
|
||||
{2,2},
|
||||
{3,3},
|
||||
{4,4},
|
||||
}
|
||||
for _, c in pairs(connections) do
|
||||
local b1 = boat.hold_whitebelts[nth][c[1]]
|
||||
local b2 = boat.hold_whitebelts[nth-1][c[2]]
|
||||
b1.connect_linked_belts(b2)
|
||||
end
|
||||
connections = {
|
||||
{5,7},
|
||||
{6,8},
|
||||
{7,9},
|
||||
{8,10},
|
||||
}
|
||||
for _, c in pairs(connections) do
|
||||
local b1 = boat.hold_whitebelts[nth][c[1]]
|
||||
local b2 = boat.hold_whitebelts[1][c[2]]
|
||||
b1.connect_linked_belts(b2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
if args.p.x < Public.Data.width/2-5 and args.p.x > Public.Data.width/2-10 and args.p.y > Public.Data.height/2 - 2 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = CoreData.static_boat_floor, position = args.p}
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Public.chunk_structures()
|
||||
return nil
|
||||
end
|
||||
|
||||
return Public
|
391
maps/pirates/surfaces/islands/common.lua
Normal file
391
maps/pirates/surfaces/islands/common.lua
Normal file
@ -0,0 +1,391 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
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 _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
|
||||
|
||||
function Public.place_water_tile(args)
|
||||
|
||||
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}
|
||||
|
||||
local fishrng = Math.random(350)
|
||||
if fishrng == 350 then
|
||||
args.entities[#args.entities + 1] = {name = 'fish', position = args.p}
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if not args.noise_generator['height'] then return end
|
||||
|
||||
local height_noise = args.noise_generator['height'](args.p)
|
||||
if height_noise < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
|
||||
local fishrng = Math.random(350)
|
||||
if fishrng == 350 then
|
||||
args.entities[#args.entities + 1] = {name = 'fish', position = args.p}
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function Public.island_height_1(args)
|
||||
local noise_name = 'height'
|
||||
|
||||
if not args.noise_generator[noise_name] then
|
||||
args.noise_generator:addNoise(noise_name,
|
||||
function(p)
|
||||
local r2 = (p.x)^2 + (p.y)^2
|
||||
local r = Math.sqrt(r2)
|
||||
|
||||
-- 'noise testing suite':
|
||||
-- local height_noise
|
||||
-- if args.noise_generator.forest then
|
||||
-- height_noise = args.noise_generator.forest(p)
|
||||
-- else return 0 end
|
||||
-- local height_noise = args.noise_generator.height_background(p)
|
||||
-- local height_noise = (
|
||||
-- 1 - r/(args.noise_generator.radius{x = p.x/r, y = p.y/r})
|
||||
-- )
|
||||
local height_noise = (
|
||||
1 - r/(args.noise_generator.radius{x = p.x/r, y = p.y/r})
|
||||
) + args.noise_generator.height_background(p)
|
||||
|
||||
return height_noise
|
||||
end)
|
||||
end
|
||||
return args.noise_generator[noise_name]
|
||||
end
|
||||
|
||||
|
||||
function Public.island_height_mostly_circular(args)
|
||||
local noise_name = 'height'
|
||||
|
||||
if not args.noise_generator[noise_name] then
|
||||
args.noise_generator:addNoise(noise_name,
|
||||
function(p)
|
||||
local r2 = (p.x)^2 + (p.y)^2
|
||||
local r = Math.sqrt(r2)
|
||||
|
||||
-- 'noise testing suite':
|
||||
-- local height_noise
|
||||
-- if args.noise_generator.forest then
|
||||
-- height_noise = args.noise_generator.forest(p)
|
||||
-- else return 0 end
|
||||
-- local height_noise = args.noise_generator.height_background(p)
|
||||
-- local height_noise = (
|
||||
-- 1 - r/(args.noise_generator.radius{x = p.x/r, y = p.y/r})
|
||||
-- )
|
||||
local height_noise = (
|
||||
1 - r/(args.noise_generator.radius{x = p.x/r, y = p.y/r})
|
||||
)
|
||||
|
||||
return height_noise
|
||||
end)
|
||||
end
|
||||
return args.noise_generator[noise_name]
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.island_height_horseshoe(args)
|
||||
local noise_name = 'height'
|
||||
|
||||
if not args.noise_generator[noise_name] then
|
||||
args.noise_generator:addNoise(noise_name,
|
||||
function(p)
|
||||
local r12 = (p.x)^2 + (p.y)^2
|
||||
local r1 = Math.sqrt(r12)
|
||||
|
||||
local offsetp = {x = p.x + 80, y = p.y}
|
||||
local r22 = (offsetp.x)^2 + (offsetp.y)^2
|
||||
local r2 = Math.sqrt(r22)
|
||||
|
||||
-- 'noise testing suite':
|
||||
-- local height_noise
|
||||
-- if args.noise_generator.forest then
|
||||
-- height_noise = args.noise_generator.forest(p)
|
||||
-- else return 0 end
|
||||
-- local height_noise = args.noise_generator.height_background(p)
|
||||
-- local height_noise = (
|
||||
-- 1 - r/(args.noise_generator.radius{x = p.x/r, y = p.y/r})
|
||||
-- )
|
||||
local height_noise = (
|
||||
1 - r1/(args.noise_generator.radius1{x = p.x/r1, y = p.y/r1})
|
||||
) - Math.max(0,
|
||||
1 - r2/(args.noise_generator.radius2{x = offsetp.x/r2, y = offsetp.y/r2})
|
||||
) + args.noise_generator.height_background(p)
|
||||
|
||||
return height_noise
|
||||
end)
|
||||
end
|
||||
return args.noise_generator[noise_name]
|
||||
end
|
||||
|
||||
|
||||
function Public.island_farness_1(args)
|
||||
--on a scale from 0 to 1, how 'far' the point is from the boat dropoff point
|
||||
if not args.static_params.width and args.static_params.islandcenter_position and args.static_params.terraingen_coordinates_offset then return end -- can only call after detailed static_params are generated
|
||||
|
||||
local noise_name = 'farness' --might as well remember as a noise just to memoize
|
||||
if not args.noise_generator[noise_name] then
|
||||
args.noise_generator:addNoise(noise_name,
|
||||
function(p)
|
||||
local island_width = args.static_params.width - 2*Math.abs(args.static_params.islandcenter_position.x)
|
||||
|
||||
local nexus_of_boredom = {x = args.static_params.terraingen_coordinates_offset.x + args.static_params.islandcenter_position.x - 2/5*island_width, y = args.static_params.terraingen_coordinates_offset.y + args.static_params.islandcenter_position.y}
|
||||
|
||||
local relativeradius2 = Math.distance(p, nexus_of_boredom)
|
||||
local farness = Math.slopefromto(relativeradius2, island_width/12, island_width)
|
||||
|
||||
if p.x < nexus_of_boredom.x then
|
||||
local num = Math.abs(nexus_of_boredom.y - p.y)
|
||||
local denom = Math.abs(nexus_of_boredom.x - p.x)
|
||||
if denom < 1 then denom = 1 end
|
||||
farness = farness * Math.slopefromto(num/denom, 1, 5)
|
||||
end
|
||||
|
||||
return farness
|
||||
end)
|
||||
end
|
||||
|
||||
return args.noise_generator[noise_name]
|
||||
end
|
||||
|
||||
|
||||
function Public.island_farness_horseshoe(args)
|
||||
--on a scale from 0 to 1, how 'far' the point is from the boat dropoff point
|
||||
--compared to first farness function this one is much more simply just distance from boat
|
||||
if not args.static_params.width and args.static_params.islandcenter_position and args.static_params.terraingen_coordinates_offset then return end -- can only call after detailed static_params are generated
|
||||
|
||||
local noise_name = 'farness' --might as well remember as a noise just to memoize
|
||||
if not args.noise_generator[noise_name] then
|
||||
args.noise_generator:addNoise(noise_name,
|
||||
function(p)
|
||||
local island_width = args.static_params.width - 2*Math.abs(args.static_params.islandcenter_position.x)
|
||||
|
||||
local nexus_of_boredom = {x = args.static_params.terraingen_coordinates_offset.x + args.static_params.islandcenter_position.x - 1/6*island_width, y = args.static_params.terraingen_coordinates_offset.y + args.static_params.islandcenter_position.y}
|
||||
|
||||
local relativeradius2 = Math.distance(p, nexus_of_boredom)
|
||||
local farness = Math.slopefromto(relativeradius2, island_width/12, 62/100*island_width)
|
||||
|
||||
return farness
|
||||
end)
|
||||
end
|
||||
|
||||
return args.noise_generator[noise_name]
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.enemies_1(args, spec, no_worms, worm_evo_bonus)
|
||||
worm_evo_bonus = worm_evo_bonus or 0
|
||||
|
||||
for x = args.left_top.x, args.left_top.x + 31 do
|
||||
for y = args.left_top.y, args.left_top.y + 31 do
|
||||
local p = {x = x, y = y}
|
||||
local spec2 = spec(p)
|
||||
if spec2.placeable and Math.random() < spec2.density_perchunk/(32*32) then
|
||||
local memory = Memory.get_crew_memory()
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
local rng = Math.random(10)
|
||||
if rng >= 4 then
|
||||
args.entities[#args.entities + 1] = {name = 'biter-spawner', position = p, force = enemy_force_name, indestructible = spec2.spawners_indestructible or false}
|
||||
elseif rng >= 3 then
|
||||
args.entities[#args.entities + 1] = {name = 'spitter-spawner', position = p, force = enemy_force_name, indestructible = spec2.spawners_indestructible or false}
|
||||
elseif not no_worms then
|
||||
local evolution = memory.evolution_factor + worm_evo_bonus
|
||||
|
||||
args.entities[#args.entities + 1] = {name = Common.get_random_worm_type(evolution + 0.05), position = p, force = enemy_force_name}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.enemies_specworms_separate(args, spec)
|
||||
|
||||
for x = args.left_top.x, args.left_top.x + 31 do
|
||||
for y = args.left_top.y, args.left_top.y + 31 do
|
||||
local p = {x = x, y = y}
|
||||
local spec2 = spec(p)
|
||||
if spec2.placeable and Math.random() < spec2.spawners_density_perchunk/(32*32) then
|
||||
local memory = Memory.get_crew_memory()
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
local rng = Math.random(10)
|
||||
if rng >=8 then
|
||||
args.entities[#args.entities + 1] = {name = 'spitter-spawner', position = p, force = enemy_force_name, indestructible = spec2.spawners_indestructible or false}
|
||||
else
|
||||
args.entities[#args.entities + 1] = {name = 'biter-spawner', position = p, force = enemy_force_name, indestructible = spec2.spawners_indestructible or false}
|
||||
end
|
||||
elseif spec2.placeable and Math.random() < spec2.worms_density_perchunk/(32*32) then
|
||||
local memory = Memory.get_crew_memory()
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
|
||||
local evolution = game.forces[enemy_force_name].evolution_factor
|
||||
|
||||
args.entities[#args.entities + 1] = {name = Common.get_random_worm_type(evolution + 0.05), position = p, force = enemy_force_name}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.assorted_structures_1(args, spec)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local overworldx = memory.overworldx or 0
|
||||
|
||||
local rng = Math.random()
|
||||
local left_top = args.left_top
|
||||
|
||||
-- initial attempt, to avoid placing two structures too close to each other, is to divide up the map into 2x2 chonks, and spawn once in each
|
||||
local bool1, bool2 = left_top.x % 64 < 32, left_top.y % 64 < 32
|
||||
local all_four_chunks = {
|
||||
{x = left_top.x, y = left_top.y},
|
||||
{x = left_top.x + (bool1 and 32 or -32), y = left_top.y},
|
||||
{x = left_top.x, y = left_top.y + (bool2 and 32 or -32)},
|
||||
{x = left_top.x + (bool1 and 32 or -32), y = left_top.y + (bool2 and 32 or -32)},
|
||||
}
|
||||
|
||||
if not args.other_map_generation_data.chunks_loaded then args.other_map_generation_data.chunks_loaded = {} end
|
||||
local chunks_loaded = args.other_map_generation_data.chunks_loaded
|
||||
|
||||
if not chunks_loaded[args.left_top.x] then chunks_loaded[args.left_top.x] = {} end
|
||||
chunks_loaded[args.left_top.x][args.left_top.y] = true
|
||||
|
||||
local nearby_chunks_generated_count = 0
|
||||
for i=1,4 do
|
||||
if chunks_loaded[all_four_chunks[i].x] and chunks_loaded[all_four_chunks[i].x][all_four_chunks[i].y] then
|
||||
nearby_chunks_generated_count = nearby_chunks_generated_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
if nearby_chunks_generated_count == 4 then --should trigger only once per 4 chunks
|
||||
local avgleft_top = {
|
||||
x = (all_four_chunks[1].x + all_four_chunks[4].x)/2,
|
||||
y = (all_four_chunks[1].y + all_four_chunks[4].y)/2,
|
||||
}
|
||||
local leftmost_topmost = {
|
||||
x = avgleft_top.x - 16,
|
||||
y = avgleft_top.y - 16,
|
||||
}
|
||||
|
||||
local spec2 = spec{x = avgleft_top.x + 16, y = avgleft_top.y + 16}
|
||||
|
||||
if rng < spec2.chanceper4chunks then
|
||||
|
||||
local rng2 = Math.random()
|
||||
local struct
|
||||
|
||||
if overworldx <= 120 then
|
||||
if rng2 < 20/100 then
|
||||
struct = Structures.IslandStructures.ROC.lonely_storage_tank
|
||||
elseif rng2 < 40/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_crashed_ship
|
||||
elseif rng2 < 50/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_oilrig_base
|
||||
elseif rng2 < 60/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_abandoned_refinery
|
||||
elseif rng2 < 70/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_mining_base
|
||||
else
|
||||
struct = Structures.IslandStructures.MATTISSO.small_primitive_mining_base
|
||||
end
|
||||
elseif overworldx <= 240 then
|
||||
if rng2 < 30/100 then
|
||||
struct = Structures.IslandStructures.ROC.lonely_storage_tank
|
||||
elseif rng2 < 40/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_crashed_ship
|
||||
elseif rng2 < 50/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_oilrig_base
|
||||
elseif rng2 < 70/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_abandoned_refinery
|
||||
elseif rng2 < 80/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_mining_base
|
||||
else
|
||||
struct = Structures.IslandStructures.MATTISSO.small_solar_base
|
||||
end
|
||||
else
|
||||
if rng2 < 10/100 then
|
||||
struct = Structures.IslandStructures.ROC.lonely_storage_tank
|
||||
elseif rng2 < 20/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_crashed_ship
|
||||
elseif rng2 < 40/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_oilrig_base
|
||||
elseif rng2 < 50/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_abandoned_refinery
|
||||
elseif rng2 < 60/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_mining_base
|
||||
elseif rng2 < 80/100 then
|
||||
struct = Structures.IslandStructures.MATTISSO.small_solar_base
|
||||
else
|
||||
struct = Structures.IslandStructures.MATTISSO.small_roboport_base
|
||||
end
|
||||
end
|
||||
|
||||
if struct then
|
||||
Structures.try_place(struct, args.specials, leftmost_topmost, 64, 64, function(p) return spec(p).placeable end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.random_rock_1(p)
|
||||
local rock_raffle = {'sand-rock-big','sand-rock-big','rock-big','rock-big','rock-big','rock-big','rock-huge','rock-huge'}
|
||||
local s_rock_raffle = #rock_raffle
|
||||
|
||||
return {name = rock_raffle[Math.random(1, s_rock_raffle)], position = p}
|
||||
end
|
||||
|
||||
function Public.random_tree_1(p)
|
||||
local tree_raffle = {
|
||||
'tree-01',
|
||||
'tree-02',
|
||||
'tree-02-red',
|
||||
'tree-03',
|
||||
'tree-04',
|
||||
'tree-05',
|
||||
'tree-06',
|
||||
'tree-06-brown',
|
||||
'tree-07',
|
||||
'tree-08',
|
||||
'tree-08-brown',
|
||||
'tree-08-red',
|
||||
'tree-09',
|
||||
'tree-09-brown',
|
||||
'tree-09-red'
|
||||
}
|
||||
local s_tree_raffle = #tree_raffle
|
||||
|
||||
return {name = tree_raffle[Math.random(1, s_tree_raffle)], position = p}
|
||||
end
|
||||
|
||||
return Public
|
71
maps/pirates/surfaces/islands/first/data.lua
Normal file
71
maps/pirates/surfaces/islands/first/data.lua
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Fledgling Vale'}
|
||||
|
||||
Public.terraingen_frame_width = 325
|
||||
Public.terraingen_frame_height = 325
|
||||
Public.static_params_default = {
|
||||
starting_time_of_day = 0,
|
||||
daynightcycletype = 1,
|
||||
boat_extra_distance_from_shore = 0,
|
||||
-- boat_extra_distance_from_shore = 0.1 * Common.boat_default_starting_distance_from_shore,
|
||||
default_decoratives = true,
|
||||
base_starting_treasure = 2000,
|
||||
base_starting_rock_material = 800,
|
||||
base_starting_wood = 2400,
|
||||
}
|
||||
|
||||
function Public.base_ores()
|
||||
return {
|
||||
['copper-ore'] = 1.9,
|
||||
['iron-ore'] = 4.2,
|
||||
['coal'] = 3.1,
|
||||
['stone'] = 0.4,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 125
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1},
|
||||
-- {wavelength = 2.5, amplitude = rscale * 0.1},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'island1',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- {upperscale = 1000, amplitude = hscale * 200},
|
||||
{upperscale = 600, amplitude = 0.15},
|
||||
},
|
||||
},
|
||||
|
||||
forest = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 70, amplitude = 1},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 120, amplitude = 1, seedfactor = 2},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
return Public
|
116
maps/pirates/surfaces/islands/first/first.lua
Normal file
116
maps/pirates/surfaces/islands/first/first.lua
Normal file
@ -0,0 +1,116 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- 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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.first.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_1(args)
|
||||
ret.forest = args.noise_generator.forest
|
||||
ret.forest_abs = function (p) return Math.abs(ret.forest(p)) end
|
||||
ret.forest_abs_suppressed = function (p) return ret.forest_abs(p) - 1 * Math.slopefromto(ret.height(p), 0.35, 0.1) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
if noises.height(p) < 0.1 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
-- if args.specials and noises.farness(p) > 0.0001 and noises.farness(p) < 0.6 and Math.random(150) == 1 then
|
||||
-- args.specials[#args.specials + 1] = {name = 'buried-treasure', position = args.p}
|
||||
-- end
|
||||
elseif noises.height(p) < 0.16 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-4', position = args.p}
|
||||
else
|
||||
if noises.forest_abs_suppressed(p) > 0.5 and noises.rock(p) < 0.3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-3', position = args.p}
|
||||
elseif noises.forest_abs_suppressed(p) > 0.2 and noises.rock(p) < 0.3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-2', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-1', position = args.p}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.height(p) > 0.2 then
|
||||
if noises.forest_abs(p) > 0.65 then
|
||||
local treedensity = 0.4 * Math.slopefromto(noises.forest_abs_suppressed(p), 0.6, 0.85)
|
||||
if noises.forest(p) > 0.87 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-01', position = args.p, visible_on_overworld = true} end
|
||||
elseif noises.forest(p) < -1.4 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-03', position = args.p, visible_on_overworld = true} end
|
||||
else
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-02', position = args.p, visible_on_overworld = true} end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.6 then
|
||||
if noises.height(p) > 0.12 then
|
||||
local rockdensity = 0.0018 * Math.slopefromto(noises.rock_abs(p), -0.15, 0.3)
|
||||
local rockrng = Math.random()
|
||||
if rockrng < rockdensity then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
elseif rockrng < rockdensity * 1.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-medium', position = args.p}
|
||||
elseif rockrng < rockdensity * 2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-small', position = args.p}
|
||||
elseif rockrng < rockdensity * 2.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-tiny', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.farness(p) > 0.4,
|
||||
density_perchunk = 28 * Math.slopefromto(noises.farness(p), 0.4, 1)^2,
|
||||
}
|
||||
end
|
||||
|
||||
IslandsCommon.enemies_1(args, spec, false, 0.4)
|
||||
end
|
||||
|
||||
|
||||
function Public.break_rock(surface, p, entity_name)
|
||||
return Ores.try_ore_spawn(surface, p, entity_name, 8)
|
||||
end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
return Hunt.silo_setup_position()
|
||||
end
|
||||
|
||||
|
||||
return Public
|
92
maps/pirates/surfaces/islands/horseshoe/data.lua
Normal file
92
maps/pirates/surfaces/islands/horseshoe/data.lua
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Shark Keys', 'Little Keys', 'Little Keys'}
|
||||
|
||||
Public.terraingen_frame_width = 896
|
||||
Public.terraingen_frame_height = 896
|
||||
Public.static_params_default = {
|
||||
starting_time_of_day = 0,
|
||||
daynightcycletype = 1,
|
||||
default_decoratives = true,
|
||||
base_starting_treasure = 1000,
|
||||
base_starting_rock_material = 800,
|
||||
base_starting_wood = 1200,
|
||||
base_starting_treasure_maps = 0,
|
||||
}
|
||||
|
||||
function Public.base_ores()
|
||||
return {
|
||||
['copper-ore'] = 2.4,
|
||||
['iron-ore'] = 3.9,
|
||||
['coal'] = 3.6,
|
||||
['stone'] = 0.8,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale1 = 240
|
||||
local rscale2 = 210
|
||||
local hscale = 0.1
|
||||
Public.noiseparams = {
|
||||
radius1 = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale1 * 1},
|
||||
{wavelength = 1.6, amplitude = rscale1 * 0.2},
|
||||
},
|
||||
},
|
||||
radius2 = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale2 * 1},
|
||||
{wavelength = 1.6, amplitude = rscale2 * 0.2},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'island1',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- {upperscale = 1000, amplitude = hscale * 200},
|
||||
{upperscale = 1600, amplitude = hscale * 1},
|
||||
{upperscale = 80, amplitude = hscale * 0.1},
|
||||
},
|
||||
},
|
||||
|
||||
forest = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 90, amplitude = 1},
|
||||
-- {upperscale = 0, amplitude = 0.15},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 110, amplitude = 1, seedfactor = 2},
|
||||
},
|
||||
},
|
||||
|
||||
mood = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 250, amplitude = 70},
|
||||
{wavelength = 50, amplitude = 20},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
148
maps/pirates/surfaces/islands/horseshoe/horseshoe.lua
Normal file
148
maps/pirates/surfaces/islands/horseshoe/horseshoe.lua
Normal file
@ -0,0 +1,148 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- 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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.horseshoe.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_horseshoe(args)
|
||||
ret.forest = args.noise_generator.forest
|
||||
ret.forest_abs = function (p) return Math.abs(ret.forest(p)) end
|
||||
ret.forest_abs_suppressed = function (p) return ret.forest_abs(p) - 2 * Math.slopefromto(ret.height(p), 0.2, 0.12) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.mood = args.noise_generator.mood
|
||||
ret.farness = IslandsCommon.island_farness_horseshoe(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
if noises.height(p) < 0.05 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
if (not args.iconized_generation) and noises.farness(p) > 0.02 and noises.farness(p) < 0.6 and Math.random(500) == 1 then
|
||||
args.specials[#args.specials + 1] = {name = 'buried-treasure', position = args.p}
|
||||
end
|
||||
elseif noises.height(p) < 0.12 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-2', position = args.p}
|
||||
else
|
||||
if noises.forest_abs_suppressed(p) > 0.3 and noises.rock(p) < -0.1 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'dirt-1', position = args.p}
|
||||
else
|
||||
if noises.mood(p) > 0.66 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
if Math.random(100) == 1 then
|
||||
args.entities[#args.entities + 1] = {name = 'fish', position = args.p}
|
||||
end
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-3', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (not args.iconized_generation) and noises.height(p) > 0 and Math.random(6000) == 1 then --but has lots of chests due to spawning anywhere
|
||||
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
|
||||
elseif noises.height(p) > 0.02 then
|
||||
if noises.forest_abs_suppressed(p) > 0.58 then
|
||||
local forest_noise = noises.forest(p)
|
||||
local treedensity
|
||||
if forest_noise > 0 then
|
||||
treedensity = 0.5 * Math.slopefromto(noises.forest_abs_suppressed(p), 0.58, 0.75)
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-06', position = args.p, visible_on_overworld = true} end
|
||||
elseif noises.forest_abs_suppressed(p) > 0.68 then
|
||||
treedensity = 0.5 * Math.slopefromto(forest_noise, -0.7, -0.75)
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-08-brown', position = args.p, visible_on_overworld = true} end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.45 then
|
||||
|
||||
if noises.height(p) > 0.05 then
|
||||
if noises.rock_abs(p) > 0.15 then
|
||||
local rockdensity = 1/500 * Math.slopefromto(noises.rock_abs(p), 0.15, 0.5)
|
||||
if noises.height(p) < 0.12 then rockdensity = rockdensity * 3 end
|
||||
local rockrng = Math.random()
|
||||
if rockrng < rockdensity then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
elseif rockrng < rockdensity * 1.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-medium', position = args.p}
|
||||
elseif rockrng < rockdensity * 2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-small', position = args.p}
|
||||
elseif rockrng < rockdensity * 2.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-tiny', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.height(p) > 0.18 and noises.mood(p) > 0.2 then
|
||||
if noises.forest_abs(p) < 0.2 and noises.rock_abs(p) > 1.8 then
|
||||
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 8}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.farness(p) > 0.35,
|
||||
spawners_indestructible = false,
|
||||
-- spawners_indestructible = noises.farness(p) > 0.7,
|
||||
density_perchunk = 10 * Math.slopefromto(noises.mood(p), 0.12, -0.18) * Math.slopefromto(noises.farness(p), 0.35, 1) * args.biter_base_density_scale,
|
||||
}
|
||||
end
|
||||
|
||||
IslandsCommon.enemies_1(args, spec)
|
||||
|
||||
-- local spec2 = function(p)
|
||||
-- local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
-- return {
|
||||
-- placeable = noises.height(p) >= 0 and noises.forest_abs_suppressed(p) < 0.3 + Math.max(0, 0.2 - noises.height(p)),
|
||||
-- chanceper4chunks = 0.5 * Math.slopefromto(noises.farness(p), 0.1, 0.4) * Math.slopefromto(noises.mood(p), 0, 0.25),
|
||||
-- }
|
||||
-- end
|
||||
-- IslandsCommon.assorted_structures_1(args, spec2)
|
||||
end
|
||||
|
||||
|
||||
function Public.break_rock(surface, p, entity_name)
|
||||
return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
return Hunt.silo_setup_position(0, 30)
|
||||
end
|
||||
|
||||
|
||||
return Public
|
338
maps/pirates/surfaces/islands/hunt.lua
Normal file
338
maps/pirates/surfaces/islands/hunt.lua
Normal file
@ -0,0 +1,338 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
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 IslandsCommon = require 'maps.pirates.surfaces.islands.common'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
local Public = {}
|
||||
|
||||
-- two things to 'hunt':
|
||||
-- treasure map for X
|
||||
-- quest treasure
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.silo_setup_position(x_fractional_offset, x_absolute_offset)
|
||||
x_absolute_offset = x_absolute_offset or 0
|
||||
x_fractional_offset = x_fractional_offset or 0
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
local boatposition = memory.boat.position
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local difficulty_offset = (1 - Common.difficulty()) * 20 or 0
|
||||
|
||||
local silo_count = Balance.silo_count()
|
||||
|
||||
local p = {
|
||||
x = Math.min(
|
||||
Math.floor(boatposition.x + difficulty_offset + (island_center.x - boatposition.x) * 3/5) - 0.5,
|
||||
Math.floor(boatposition.x + 175) - 0.5
|
||||
) + (island_center.x - boatposition.x) * x_fractional_offset + x_absolute_offset,
|
||||
y = Math.floor(boatposition.y + (island_center.y - boatposition.y) * 3/5) - 0.5
|
||||
}
|
||||
|
||||
local tries = 0
|
||||
local p_ret = nil
|
||||
local p2
|
||||
while p_ret == nil and tries < 200 do
|
||||
p2 = {x = p.x + Math.random(-30, 0), y = p.y + Math.random(-70, 70)}
|
||||
if p2.x >= boatposition.x+5 and Common.can_place_silo_setup(surface, p2, silo_count) then p_ret = p2 end
|
||||
tries = tries + 1
|
||||
end
|
||||
while p_ret == nil and tries < 400 do
|
||||
p2 = {x = p.x + Math.random(-60, 10), y = p.y + Math.random(-90, 90)}
|
||||
if p2.x >= boatposition.x+5 and Common.can_place_silo_setup(surface, p2, silo_count, true) then p_ret = p2 end
|
||||
tries = tries + 1
|
||||
end
|
||||
while p_ret == nil and tries < 1200 do
|
||||
p2 = {x = p.x + Math.random(-90, 20), y = p.y + Math.random(-130, 130)}
|
||||
if p2.x >= boatposition.x+5 and Common.can_place_silo_setup(surface, p2, silo_count, true) then p_ret = p2 end
|
||||
tries = tries + 1
|
||||
end
|
||||
-- if _DEBUG then
|
||||
if p_ret == nil then
|
||||
log("No good position found after 1200 tries")
|
||||
p_ret = p
|
||||
else
|
||||
log(string.format("Silo position generated after %f tries: %f, %f", tries, p_ret.x, p_ret.y))
|
||||
end
|
||||
-- end
|
||||
|
||||
Common.ensure_chunks_at(surface, p_ret, 1)
|
||||
return p_ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.mid_farness_position_1(args, points_to_avoid)
|
||||
points_to_avoid = points_to_avoid or {}
|
||||
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local width = destination.static_params.width
|
||||
local height = destination.static_params.height
|
||||
|
||||
local tries = 0
|
||||
local p_ret = nil
|
||||
|
||||
local p2
|
||||
while p_ret == nil and tries < 400 do
|
||||
p2 = {x = island_center.x + Math.random(Math.ceil(-width/2), Math.ceil(width/2)), y = island_center.y + Math.random(Math.ceil(-height/2), Math.ceil(height/2))}
|
||||
|
||||
Common.ensure_chunks_at(surface, p2, 0.01)
|
||||
|
||||
local tile = surface.get_tile(p2)
|
||||
if tile and tile.valid and tile.name then
|
||||
if (not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name)) and (not Utils.contains(CoreData.edgemost_tile_names, tile.name)) then
|
||||
local p3 = {x = p2.x + args.static_params.terraingen_coordinates_offset.x, y = p2.y + args.static_params.terraingen_coordinates_offset.y}
|
||||
|
||||
if IslandsCommon.island_farness_1(args)(p3) > 0.1 and IslandsCommon.island_farness_1(args)(p3) < 0.8 then
|
||||
local allowed = true
|
||||
for _, pa in pairs(points_to_avoid) do
|
||||
if Math.distance({x = pa.x, y = pa.y}, p2) < pa.r then
|
||||
allowed = false
|
||||
end
|
||||
end
|
||||
if allowed then
|
||||
p_ret = p2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tries = tries + 1
|
||||
end
|
||||
|
||||
if _DEBUG then
|
||||
if p_ret == nil then
|
||||
log("No good mid_farness_position_1 position found after 500 tries")
|
||||
-- p_ret = {x = 0, y = 0}
|
||||
else
|
||||
log(string.format("mid_farness_position_1 Position found after %f tries: %f, %f", tries, p_ret.x, p_ret.y))
|
||||
end
|
||||
end
|
||||
|
||||
return p_ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.close_position_try_avoiding_entities(args, points_to_avoid, farness_boost_low, farness_boost_high)
|
||||
farness_boost_low = farness_boost_low or 0
|
||||
farness_boost_high = farness_boost_high or 0
|
||||
points_to_avoid = points_to_avoid or {}
|
||||
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local width = destination.static_params.width
|
||||
local height = destination.static_params.height
|
||||
|
||||
local tries = 0
|
||||
local p_ret = nil
|
||||
|
||||
local p2
|
||||
while p_ret == nil and tries < 700 do
|
||||
p2 = {x = island_center.x + Math.random(Math.ceil(-width/2), 0), y = island_center.y + Math.random(Math.ceil(-height/3), Math.ceil(height/3))}
|
||||
|
||||
Common.ensure_chunks_at(surface, p2, 0.01)
|
||||
|
||||
local tile = surface.get_tile(p2)
|
||||
if tile and tile.valid and tile.name then
|
||||
if (not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name)) and (not Utils.contains(CoreData.edgemost_tile_names, tile.name)) then
|
||||
local p3 = {x = p2.x + args.static_params.terraingen_coordinates_offset.x, y = p2.y + args.static_params.terraingen_coordinates_offset.y}
|
||||
|
||||
if IslandsCommon.island_farness_1(args)(p3) > 0.06 + farness_boost_low and IslandsCommon.island_farness_1(args)(p3) < 0.19 + farness_boost_high then
|
||||
local allowed = true
|
||||
if tries < 40 and #surface.find_entities({{p2.x - 8, p2.y - 8}, {p2.x + 8, p2.y + 8}}) > 0 then
|
||||
allowed = false
|
||||
end
|
||||
if tries >= 40 and tries < 100 and #surface.find_entities({{p2.x - 6, p2.y - 6}, {p2.x + 6, p2.y + 6}}) > 0 then
|
||||
allowed = false
|
||||
end
|
||||
if tries >= 100 and tries < 200 and #surface.find_entities({{p2.x - 3, p2.y - 3}, {p2.x + 3, p2.y + 3}}) > 0 then
|
||||
allowed = false
|
||||
end
|
||||
for _, pa in pairs(points_to_avoid) do
|
||||
if allowed and Math.distance({x = pa.x, y = pa.y}, p2) < pa.r then
|
||||
allowed = false
|
||||
end
|
||||
end
|
||||
if allowed then
|
||||
p_ret = p2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tries = tries + 1
|
||||
end
|
||||
|
||||
if _DEBUG then
|
||||
if p_ret == nil then
|
||||
log("No good close_position_try_avoiding_entities found after 500 tries")
|
||||
-- p_ret = {x = 0, y = 0}
|
||||
else
|
||||
log(string.format("close_position_try_avoiding_entities found after %f tries: %f, %f", tries, p_ret.x, p_ret.y))
|
||||
end
|
||||
end
|
||||
|
||||
return p_ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.position_away_from_players_1(_, radius)
|
||||
radius = radius or 60
|
||||
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local width = destination.static_params.width
|
||||
local height = destination.static_params.height
|
||||
|
||||
local tries = 0
|
||||
local p_ret = nil
|
||||
|
||||
local p2
|
||||
while p_ret == nil and tries < 500 do
|
||||
p2 = {x = island_center.x + Math.random(Math.ceil(-width/2), Math.ceil(width/2)), y = island_center.y + Math.random(Math.ceil(-height/2), Math.ceil(height/2))}
|
||||
|
||||
Common.ensure_chunks_at(surface, p2, 0.01)
|
||||
|
||||
-- local p3 = {x = p2.x + args.static_params.terraingen_coordinates_offset.x, y = p2.y + args.static_params.terraingen_coordinates_offset.y}
|
||||
local tile = surface.get_tile(p2)
|
||||
|
||||
if tile and tile.valid and tile.name then
|
||||
if not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name) then
|
||||
local nearby_characters = surface.find_entities_filtered{position = p2, radius = radius, name = 'character'}
|
||||
if (not nearby_characters) or (#nearby_characters == 0) then
|
||||
p_ret = p2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
tries = tries + 1
|
||||
end
|
||||
|
||||
if _DEBUG then
|
||||
if p_ret == nil then
|
||||
log("No good position found after 500 tries")
|
||||
-- p_ret = {x = 0, y = 0}
|
||||
else
|
||||
log(string.format("Position found after %f tries: %f, %f", tries, p_ret.x, p_ret.y))
|
||||
end
|
||||
end
|
||||
|
||||
return p_ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.merchant_ship_position()
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local width = destination.static_params.width
|
||||
local height = destination.static_params.height
|
||||
|
||||
local right_boundary = island_center.x + width/2
|
||||
|
||||
local to_try = {}
|
||||
for i = -height/2, height/2, 10 do
|
||||
to_try[#to_try + 1] = i
|
||||
end
|
||||
Math.shuffle(to_try)
|
||||
|
||||
local last_reasonable_position
|
||||
local p_ret
|
||||
for _, h in ipairs(to_try) do
|
||||
local right_boundary_p = {x = right_boundary, y = h}
|
||||
|
||||
Common.ensure_chunks_at(surface, right_boundary_p, 10)
|
||||
|
||||
local i = 0
|
||||
while i < 300 and (not p_ret) do
|
||||
i = i + 1
|
||||
|
||||
local p2 = {x = right_boundary - i, y = h}
|
||||
|
||||
local tile = surface.get_tile(p2)
|
||||
if i < 32 then
|
||||
if not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name) then
|
||||
break
|
||||
end
|
||||
else
|
||||
if not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name) then
|
||||
local area = {{p2.x - 40, p2.y - 11},{p2.x + 4, p2.y + 11}}
|
||||
|
||||
local spawners = surface.find_entities_filtered({type = 'unit-spawner', force = memory.enemy_force_name, area = area})
|
||||
local worms = surface.find_entities_filtered({type = 'turret', force = memory.enemy_force_name, area = area})
|
||||
if #spawners == 0 and #worms == 0 then
|
||||
p_ret = p2
|
||||
else
|
||||
last_reasonable_position = p2
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if _DEBUG then
|
||||
if p_ret == nil then
|
||||
log("No good position found for merchant ship")
|
||||
-- p_ret = {x = 0, y = 0}
|
||||
else
|
||||
log(string.format("Merchant ship position found: %f, %f", p_ret.x, p_ret.y))
|
||||
end
|
||||
end
|
||||
|
||||
return p_ret or last_reasonable_position
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
409
maps/pirates/surfaces/islands/islands.lua
Normal file
409
maps/pirates/surfaces/islands/islands.lua
Normal file
@ -0,0 +1,409 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local Structures = require 'maps.pirates.structures.structures'
|
||||
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'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
local Token = require 'utils.token'
|
||||
local Task = require 'utils.task'
|
||||
|
||||
local Public = {}
|
||||
local enum = IslandsCommon.enum
|
||||
Public.enum = enum
|
||||
|
||||
Public[enum.FIRST] = require 'maps.pirates.surfaces.islands.first.first'
|
||||
Public[enum.STANDARD] = require 'maps.pirates.surfaces.islands.standard.standard'
|
||||
Public[enum.STANDARD_VARIANT] = require 'maps.pirates.surfaces.islands.standard_variant.standard_variant'
|
||||
Public[enum.WALKWAYS] = require 'maps.pirates.surfaces.islands.walkways.walkways'
|
||||
Public[enum.RADIOACTIVE] = require 'maps.pirates.surfaces.islands.radioactive.radioactive'
|
||||
Public[enum.RED_DESERT] = require 'maps.pirates.surfaces.islands.red_desert.red_desert'
|
||||
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['IslandsCommon'] = require 'maps.pirates.surfaces.islands.common'
|
||||
|
||||
|
||||
|
||||
local function render_silo_hp()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if not (destination.dynamic_data.rocketsilos and destination.dynamic_data.rocketsilos[1] and destination.dynamic_data.rocketsilos[1].valid) then return end
|
||||
destination.dynamic_data.rocketsilohptext = rendering.draw_text{
|
||||
text = 'HP: ' .. destination.dynamic_data.rocketsilohp .. ' / ' .. destination.dynamic_data.rocketsilomaxhp,
|
||||
surface = surface,
|
||||
target = destination.dynamic_data.rocketsilos[1],
|
||||
target_offset = {0, 4.5},
|
||||
color = {0, 255, 0},
|
||||
scale = 1.20,
|
||||
font = 'default-game',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = true
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
function Public.spawn_treasure_maps(destination, points_to_avoid)
|
||||
points_to_avoid = points_to_avoid or {}
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if not surface and surface.valid then return end
|
||||
|
||||
local num = destination.static_params.starting_treasure_maps
|
||||
if not destination.dynamic_data.treasure_maps then destination.dynamic_data.treasure_maps = {} end
|
||||
|
||||
local args = {
|
||||
static_params = destination.static_params,
|
||||
noise_generator = Utils.noise_generator({}, 0),
|
||||
}
|
||||
|
||||
for i = 1, num do
|
||||
local map = {}
|
||||
|
||||
local p = Hunt.mid_farness_position_1(args, points_to_avoid)
|
||||
|
||||
map.position = p
|
||||
map.mapobject_rendering = rendering.draw_sprite{
|
||||
surface = surface,
|
||||
target = p,
|
||||
sprite = 'utility/gps_map_icon',
|
||||
render_layer = '125',
|
||||
x_scale = 2.4,
|
||||
y_scale = 2.4,
|
||||
}
|
||||
map.state = 'on_ground'
|
||||
map.x_renderings = nil
|
||||
map.buried_treasure_position = nil
|
||||
|
||||
destination.dynamic_data.treasure_maps[#destination.dynamic_data.treasure_maps + 1] = map
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.spawn_ghosts(destination, points_to_avoid)
|
||||
points_to_avoid = points_to_avoid or {}
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if not surface and surface.valid then return end
|
||||
|
||||
if not (destination.dynamic_data and destination.dynamic_data.quest_type and destination.dynamic_data.quest_type == Quest.enum.FIND) then return end
|
||||
|
||||
local num = destination.dynamic_data.quest_progressneeded
|
||||
if not destination.dynamic_data.ghosts then destination.dynamic_data.ghosts = {} end
|
||||
|
||||
local args = {
|
||||
static_params = destination.static_params,
|
||||
noise_generator = Utils.noise_generator({}, 0),
|
||||
}
|
||||
|
||||
for i = 1, num do
|
||||
local ghost = {}
|
||||
|
||||
local p = Hunt.mid_farness_position_1(args, points_to_avoid)
|
||||
|
||||
ghost.position = p
|
||||
ghost.ghostobject_rendering = rendering.draw_sprite{
|
||||
surface = surface,
|
||||
target = p,
|
||||
sprite = 'utility/ghost_time_to_live_modifier_icon',
|
||||
render_layer = '125',
|
||||
x_scale = 1,
|
||||
y_scale = 1,
|
||||
}
|
||||
ghost.state = 'on_ground'
|
||||
|
||||
destination.dynamic_data.ghosts[#destination.dynamic_data.ghosts + 1] = ghost
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.spawn_covered(destination, points_to_avoid)
|
||||
points_to_avoid = points_to_avoid or {}
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if not surface and surface.valid then return end
|
||||
|
||||
local args = {
|
||||
static_params = destination.static_params,
|
||||
noise_generator = Utils.noise_generator({}, 0),
|
||||
}
|
||||
|
||||
local p
|
||||
for i = 1, 1 do
|
||||
p = Hunt.mid_farness_position_1(args, points_to_avoid)
|
||||
|
||||
local structureData = Structures.IslandStructures.ROC.covered1.Data
|
||||
local special = {
|
||||
position = p,
|
||||
components = structureData.components,
|
||||
width = structureData.width,
|
||||
height = structureData.height,
|
||||
name = structureData.name,
|
||||
}
|
||||
if not destination.dynamic_data.structures_waiting_to_be_placed then
|
||||
destination.dynamic_data.structures_waiting_to_be_placed = {}
|
||||
end
|
||||
destination.dynamic_data.structures_waiting_to_be_placed[#destination.dynamic_data.structures_waiting_to_be_placed + 1] = {data = special, tick = game.tick}
|
||||
|
||||
local requirement = destination.dynamic_data.covered1_requirement.price
|
||||
|
||||
local rendering1 = rendering.draw_text{
|
||||
surface = surface,
|
||||
target = {x = p.x + 4, y = p.y + 6.85},
|
||||
color = CoreData.colors.renderingtext_green,
|
||||
scale = 1.5,
|
||||
font = 'default-game',
|
||||
alignment = 'right',
|
||||
}
|
||||
local rendering2 = rendering.draw_sprite{
|
||||
sprite = 'item/' .. requirement.name,
|
||||
surface = surface,
|
||||
target = {x = p.x + 4.85, y = p.y + 7.5},
|
||||
x_scale = 1.5,
|
||||
y_scale = 1.5
|
||||
}
|
||||
|
||||
destination.dynamic_data.covered_data = {
|
||||
position = p,
|
||||
state = 'covered',
|
||||
requirement = requirement,
|
||||
rendering1 = rendering1,
|
||||
rendering2 = rendering2,
|
||||
}
|
||||
|
||||
log('covered market position: ' .. p.x .. ', ' .. p.y)
|
||||
end
|
||||
|
||||
return p
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.spawn_ores_on_arrival(destination, points_to_avoid)
|
||||
points_to_avoid = points_to_avoid or {}
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if not surface and surface.valid then return end
|
||||
|
||||
if (destination.subtype and (destination.subtype == enum.STANDARD or destination.subtype == enum.STANDARD_VARIANT or destination.subtype == enum.MAZE)) then
|
||||
local ores = {'iron-ore', 'copper-ore', 'stone', 'coal', 'crude-oil'}
|
||||
|
||||
local args = {
|
||||
static_params = destination.static_params,
|
||||
noise_generator = Utils.noise_generator({}, 0),
|
||||
}
|
||||
|
||||
local farness_boost_low, farness_boost_high = 0, 0
|
||||
if destination.subtype == enum.MAZE then
|
||||
farness_boost_low = 0.08
|
||||
farness_boost_high = 0.25
|
||||
end
|
||||
|
||||
for _, ore in pairs(ores) do
|
||||
if destination.static_params.abstract_ore_amounts[ore] then
|
||||
local p = Hunt.close_position_try_avoiding_entities(args, points_to_avoid, farness_boost_low, farness_boost_high)
|
||||
if p then points_to_avoid[#points_to_avoid + 1] = {x=p.x, y=p.y, r=11} end
|
||||
|
||||
if ore == 'crude-oil' then
|
||||
|
||||
local count = Math.max(1, Math.ceil((destination.static_params.abstract_ore_amounts[ore]/3)^(1/2)))
|
||||
local amount = Common.oil_abstract_to_real(destination.static_params.abstract_ore_amounts[ore]) / count
|
||||
|
||||
for i = 1, count do
|
||||
local p2 = {p.x + Math.random(-7, 7), p.y + Math.random(-7, 7)}
|
||||
local whilesafety = 0
|
||||
while (not surface.can_place_entity{name = 'crude-oil', position = p2}) and whilesafety < 30 do
|
||||
p2 = {p.x + Math.random(-7, 7), p.y + Math.random(-7, 7)}
|
||||
whilesafety = whilesafety + 1
|
||||
end
|
||||
|
||||
surface.create_entity{name = 'crude-oil', position = p2, amount = amount}
|
||||
end
|
||||
|
||||
destination.dynamic_data.ore_types_spawned[ore] = true
|
||||
else
|
||||
local amount = Common.ore_abstract_to_real(destination.static_params.abstract_ore_amounts[ore])
|
||||
|
||||
local placed = Ores.draw_noisy_ore_patch(surface, p, ore, amount, 10000, 30, true, true)
|
||||
|
||||
if placed > 0 then
|
||||
destination.dynamic_data.ore_types_spawned[ore] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.spawn_merchant_ship(destination)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if not surface and surface.valid then return end
|
||||
|
||||
-- local args = {
|
||||
-- static_params = destination.static_params,
|
||||
-- noise_generator = Utils.noise_generator({}, 0),
|
||||
-- }
|
||||
-- local p = Hunt.merchant_ship_position(args)
|
||||
local p = Hunt.merchant_ship_position()
|
||||
|
||||
if p then
|
||||
local boat = {
|
||||
state = Boats.enum_state.LANDED,
|
||||
type = Boats.enum.MERCHANT,
|
||||
position = p,
|
||||
force_name = 'environment',
|
||||
surface_name = surface.name,
|
||||
market = nil,
|
||||
}
|
||||
|
||||
Boats.place_landingtrack(boat, CoreData.landing_tile, true)
|
||||
|
||||
Boats.place_boat(boat, CoreData.static_boat_floor, true, true, true)
|
||||
|
||||
destination.dynamic_data.merchant_market = boat.market
|
||||
|
||||
return boat.market
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local silo_chart_tag = Token.register(
|
||||
function(data)
|
||||
local p_silo = data.p_silo
|
||||
local surface_name = data.surface_name
|
||||
|
||||
local surface = game.surfaces[surface_name]
|
||||
if not surface and surface.valid then return end
|
||||
|
||||
|
||||
Memory.set_working_id(data.crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if memory.game_lost then return end
|
||||
local destination = Common.current_destination()
|
||||
local force = memory.force
|
||||
|
||||
destination.dynamic_data.silo_chart_tag = force.add_chart_tag(surface, {icon = {type = 'item', name = 'rocket-silo'}, position = p_silo})
|
||||
end
|
||||
)
|
||||
function Public.spawn_silo_setup()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
local subtype = destination.subtype
|
||||
local force = memory.force
|
||||
|
||||
local p_silo = Public[subtype].generate_silo_setup_position()
|
||||
if not p_silo then return end
|
||||
-- log(string.format("placing silo at x=%f, y = %f", p_silo.x, p_silo.y))
|
||||
|
||||
local silo_count = Balance.silo_count()
|
||||
if not (silo_count and silo_count >= 1) then return end
|
||||
|
||||
if _DEBUG then
|
||||
if silo_count >= 2 then game.print('debug - silo count: ' .. silo_count) end
|
||||
end
|
||||
|
||||
for i=1,silo_count do
|
||||
local silo = surface.create_entity({name = 'rocket-silo', position = {p_silo.x + 9*(i-1), p_silo.y}, force = force, create_build_effect_smoke = false})
|
||||
if silo and silo.valid then
|
||||
if not destination.dynamic_data.rocketsilos then destination.dynamic_data.rocketsilos = {} end
|
||||
destination.dynamic_data.rocketsilos[#destination.dynamic_data.rocketsilos + 1]= silo
|
||||
silo.minable = false
|
||||
silo.rotatable = false
|
||||
silo.operable = false
|
||||
if i == 1 then
|
||||
silo.auto_launch = true
|
||||
else
|
||||
silo.destructible = false
|
||||
end
|
||||
local modulesinv = silo.get_module_inventory()
|
||||
modulesinv.insert{name = 'productivity-module-3', count = 4}
|
||||
end
|
||||
end
|
||||
|
||||
-- local substation = surface.create_entity({name = 'substation', position = {x = p_silo.x - 8.5, y = p_silo.y - 0.5}, force = force, create_build_effect_smoke = false})
|
||||
-- if substation and substation.valid then
|
||||
-- substation.destructible = false
|
||||
-- substation.minable = false
|
||||
-- substation.rotatable = false
|
||||
-- end
|
||||
|
||||
-- local eei = surface.create_entity({name = 'electric-energy-interface', position = {x = p_silo.x - 8.5, y = p_silo.y + 1.5}, force = force, create_build_effect_smoke = false})
|
||||
-- if eei and eei.valid then
|
||||
-- memory.islandeei = eei
|
||||
-- eei.destructible = false
|
||||
-- eei.minable = false
|
||||
-- eei.rotatable = false
|
||||
-- eei.operable = false
|
||||
-- eei.electric_buffer_size = memory.islandeeijoulesperrocket / 100
|
||||
-- eei.power_production = 0
|
||||
-- eei.power_usage = 0
|
||||
-- end
|
||||
|
||||
if CoreData.rocket_silo_death_causes_loss or (destination.static_params and destination.static_params.base_cost_to_undock and destination.static_params.base_cost_to_undock['launch_rocket'] and destination.static_params.base_cost_to_undock['launch_rocket'] == true) then
|
||||
-- we need to know where it is
|
||||
force.chart(surface, {{p_silo.x - 4, p_silo.y - 4},{p_silo.x + 4, p_silo.y + 4}})
|
||||
Task.set_timeout_in_ticks(2, silo_chart_tag, {p_silo = p_silo, surface_name = destination.surface_name, crew_id = memory.id})
|
||||
end
|
||||
|
||||
render_silo_hp()
|
||||
|
||||
return p_silo
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.spawn_enemy_boat(type)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
local offsets = {50, -50, 63, -63}
|
||||
|
||||
local enemyboats = memory.enemyboats
|
||||
if enemyboats then
|
||||
local boat = {
|
||||
state = Boats.enum_state.APPROACHING,
|
||||
type = type,
|
||||
speed = 4.5,
|
||||
position = {x = - surface.map_gen_settings.width/2 + 17.5, y = (memory.boat.dockedposition or memory.boat.position).y + offsets[Math.random(4)]},
|
||||
force_name = memory.enemy_force_name,
|
||||
surface_name = surface.name,
|
||||
unit_group = nil,
|
||||
spawner = nil,
|
||||
}
|
||||
enemyboats[#enemyboats + 1] = boat
|
||||
|
||||
Boats.place_boat(boat, CoreData.static_boat_floor, true, true)
|
||||
|
||||
local e = surface.create_entity({name = 'biter-spawner', force = boat.force_name, position = {boat.position.x + Boats.get_scope(boat).Data.spawn_point.x, boat.position.y + Boats.get_scope(boat).Data.spawn_point.y}})
|
||||
|
||||
if e and e.valid then
|
||||
-- e.destructible = false
|
||||
boat.spawner = e
|
||||
|
||||
Common.new_healthbar(false, e, 350, nil, 350, 0.3)
|
||||
end
|
||||
|
||||
return enemyboats[#enemyboats]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Public
|
57
maps/pirates/surfaces/islands/maze/data.lua
Normal file
57
maps/pirates/surfaces/islands/maze/data.lua
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Bewildering Maze'}
|
||||
|
||||
Public.terraingen_frame_width = 896
|
||||
Public.terraingen_frame_height = 896
|
||||
Public.static_params_default = {
|
||||
starting_time_of_day = 0,
|
||||
daynightcycletype = 1,
|
||||
default_decoratives = true,
|
||||
base_starting_treasure = 1000,
|
||||
base_starting_rock_material = 800,
|
||||
base_starting_wood = 1200,
|
||||
base_starting_treasure_maps = 3,
|
||||
}
|
||||
|
||||
function Public.base_ores()
|
||||
return {
|
||||
['copper-ore'] = 3.5,
|
||||
['iron-ore'] = 6.5,
|
||||
['coal'] = 4.0,
|
||||
['stone'] = 2.0,
|
||||
['crude-oil'] = 25,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 240
|
||||
-- local hscale = 0.1
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1},
|
||||
{wavelength = 1.6, amplitude = rscale * 0.15},
|
||||
},
|
||||
},
|
||||
|
||||
maze = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 250, amplitude = 70},
|
||||
{wavelength = 50, amplitude = 20},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
264
maps/pirates/surfaces/islands/maze/maze.lua
Normal file
264
maps/pirates/surfaces/islands/maze/maze.lua
Normal file
@ -0,0 +1,264 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
local Structures = require 'maps.pirates.structures.structures'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- 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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.maze.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_mostly_circular(args)
|
||||
ret.maze = args.noise_generator.maze
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
local function maze_wall(args)
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-2', position = args.p}
|
||||
if Math.random(1, 2) == 1 then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
else
|
||||
local e = IslandsCommon.random_tree_1(args.p)
|
||||
e.visible_on_overworld = true
|
||||
args.entities[#args.entities + 1] = e
|
||||
end
|
||||
end
|
||||
|
||||
local maze_scale = 24
|
||||
|
||||
local steps_orthogonal = {
|
||||
{x = 0, y = -maze_scale},
|
||||
{x = -maze_scale, y = 0},
|
||||
{x = maze_scale, y = 0},
|
||||
{x = 0, y = maze_scale}
|
||||
}
|
||||
local steps_diagonal = {
|
||||
{diagonal = {x = -maze_scale, y = maze_scale}, connection_1 = {x = -maze_scale, y = 0}, connection_2 = {x = 0, y = maze_scale}},
|
||||
{diagonal = {x = maze_scale, y = -maze_scale}, connection_1 = {x = maze_scale, y = 0}, connection_2 = {x = 0, y = -maze_scale}},
|
||||
{diagonal = {x = maze_scale, y = maze_scale}, connection_1 = {x = maze_scale, y = 0}, connection_2 = {x = 0, y = maze_scale}},
|
||||
{diagonal = {x = -maze_scale, y = -maze_scale}, connection_1 = {x = -maze_scale, y = 0}, connection_2 = {x = 0, y = -maze_scale}}
|
||||
}
|
||||
|
||||
local function get_path_connections_count(lab_cells, p)
|
||||
local connections = 0
|
||||
for _, m in pairs(steps_orthogonal) do
|
||||
if lab_cells[tostring(p.x + m.x) .. '_' .. tostring(p.y + m.y)] then
|
||||
connections = connections + 1
|
||||
end
|
||||
end
|
||||
return connections
|
||||
end
|
||||
|
||||
local function labyrinth_determine_walkable_cell(args)
|
||||
-- local noises = Public.noises(args)
|
||||
-- local mazenoise = noises.maze()
|
||||
local reduced_p = {x = args.true_p.x - (args.true_p.x % maze_scale), y = args.true_p.y - (args.true_p.y % maze_scale)}
|
||||
|
||||
if not args.other_map_generation_data.labyrinth_cells then
|
||||
args.other_map_generation_data.labyrinth_cells = {}
|
||||
end
|
||||
local lab_cells = args.other_map_generation_data.labyrinth_cells
|
||||
|
||||
if lab_cells[tostring(reduced_p.x) .. '_' .. tostring(reduced_p.y)] == true then
|
||||
return true
|
||||
elseif lab_cells[tostring(reduced_p.x) .. '_' .. tostring(reduced_p.y)] == false then
|
||||
return false
|
||||
else
|
||||
-- presumptive
|
||||
lab_cells[tostring(reduced_p.x) .. '_' .. tostring(reduced_p.y)] = false
|
||||
|
||||
for _, modifier in pairs(steps_diagonal) do
|
||||
if lab_cells[tostring(reduced_p.x + modifier.diagonal.x) .. '_' .. tostring(reduced_p.y + modifier.diagonal.y)] then
|
||||
local connection_1 = lab_cells[tostring(reduced_p.x + modifier.connection_1.x) .. '_' .. tostring(reduced_p.y + modifier.connection_1.y)]
|
||||
local connection_2 = lab_cells[tostring(reduced_p.x + modifier.connection_2.x) .. '_' .. tostring(reduced_p.y + modifier.connection_2.y)]
|
||||
if not connection_1 and not connection_2 then
|
||||
return false --sensible corners
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local max_connections = 2
|
||||
if Math.random(4) == 1 then max_connections = 3 end
|
||||
|
||||
for _, m in pairs(steps_orthogonal) do
|
||||
if get_path_connections_count(lab_cells, {x = reduced_p.x + m.x, y = reduced_p.y + m.y}) >= max_connections then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if get_path_connections_count(lab_cells, reduced_p) >= max_connections then
|
||||
return false
|
||||
end
|
||||
|
||||
-- for _, m in pairs(steps_orthogonal) do
|
||||
-- if get_path_connections_count(lab_cells, {x = reduced_p.x + m.x, y = reduced_p.y + m.y}) >= Math.random(2, 3) then
|
||||
-- return false
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if get_path_connections_count(lab_cells, reduced_p) >= Math.random(2, 3) then
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- if Math.random(80) == 1 then --dead ends and such
|
||||
-- log(reduced_p.x .. '_' .. reduced_p.y .. ' is dead end')
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
lab_cells[tostring(reduced_p.x) .. '_' .. tostring(reduced_p.y)] = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- local function terrain_entity_at_relative_position(args, entity)
|
||||
-- local relative_p = {x = args.true_p.x % maze_scale, y = args.true_p.y % maze_scale}
|
||||
|
||||
-- if relative_p.x >= entity.rel_p.x and relative_p.x < entity.rel_p.x+1 and relative_p.y >= entity.rel_p.y and relative_p.y < entity.rel_p.y+1 then
|
||||
-- entity.rel_p = nil
|
||||
-- entity.position = args.p
|
||||
-- args.entities[#args.entities + 1] = entity
|
||||
-- end
|
||||
-- end
|
||||
|
||||
local free_labyrinth_cell_raffle = {
|
||||
empty = 16.5,
|
||||
maze_labs = 0.6,
|
||||
maze_defended_camp = 0.85,
|
||||
maze_undefended_camp = 0.25,
|
||||
maze_worms = 0.8,
|
||||
small_abandoned_refinery = 0.05,
|
||||
small_roboport_base = 0.05,
|
||||
maze_belts_1 = 0.2,
|
||||
maze_belts_2 = 0.2,
|
||||
maze_belts_3 = 0.2,
|
||||
maze_belts_4 = 0.2,
|
||||
maze_mines = 0.1,
|
||||
maze_treasure = 0.7,
|
||||
}
|
||||
|
||||
local function free_labyrinth_cell_type(args)
|
||||
local reduced_p = {x = args.true_p.x - (args.true_p.x % maze_scale), y = args.true_p.y - (args.true_p.y % maze_scale)}
|
||||
|
||||
if not args.other_map_generation_data.free_labyrinth_cell_types then
|
||||
args.other_map_generation_data.free_labyrinth_cell_types = {}
|
||||
end
|
||||
local cell_types = args.other_map_generation_data.free_labyrinth_cell_types
|
||||
|
||||
local type
|
||||
if cell_types[tostring(reduced_p.x) .. '_' .. tostring(reduced_p.y)] then
|
||||
type = cell_types[tostring(reduced_p.x) .. '_' .. tostring(reduced_p.y)]
|
||||
end
|
||||
|
||||
if not type then
|
||||
type = Math.raffle2(free_labyrinth_cell_raffle)
|
||||
cell_types[tostring(reduced_p.x) .. '_' .. tostring(reduced_p.y)] = type
|
||||
end
|
||||
|
||||
return type
|
||||
end
|
||||
|
||||
local function free_labyrinth_cell_contents(args)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
-- local noises = Public.noises(args)
|
||||
-- local mazenoise = noises.maze()
|
||||
local relative_p = {x = args.true_p.x % maze_scale, y = args.true_p.y % maze_scale}
|
||||
-- local reduced_p = {x = args.true_p.x - relative_p.x, y = args.true_p.y - relative_p.y}
|
||||
|
||||
local type = free_labyrinth_cell_type(args)
|
||||
|
||||
if relative_p.x >= maze_scale/2-0.5 and relative_p.x < maze_scale/2+0.5 and relative_p.y >= maze_scale/2-0.5 and relative_p.y < maze_scale/2+0.5 then --should fire just once, and only if the center is included
|
||||
-- terrain_entity_at_relative_position(args, {name = 'lab', rel_p = {x = 15, y = 15}, force = memory.ancient_friendly_force})
|
||||
if type == 'empty' then
|
||||
return nil
|
||||
else
|
||||
Structures.tryAddStructureByName(args.specials, type, args.p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
if args.iconized_generation then
|
||||
maze_wall(args)
|
||||
else
|
||||
if noises.height(p) < 0 + Math.max(0, 0.3 - 2*noises.farness(p)) then
|
||||
if args.true_p.x < 0 and Math.abs(args.true_p.y) < 3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'stone-path', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
end
|
||||
if Math.random(500) == 1 then
|
||||
args.specials[#args.specials + 1] = {name = 'buried-treasure', position = args.p}
|
||||
end
|
||||
elseif noises.height(p) < 0.1 + Math.max(0, 0.3 - 2*noises.farness(p)/2) then
|
||||
if args.true_p.x < 0 and Math.abs(args.true_p.y) < 3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'stone-path', position = args.p}
|
||||
else
|
||||
maze_wall(args)
|
||||
end
|
||||
else -- maze itself
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-1', position = args.p}
|
||||
|
||||
if labyrinth_determine_walkable_cell(args) then
|
||||
free_labyrinth_cell_contents(args)
|
||||
else
|
||||
maze_wall(args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.farness(p) > 0.66,
|
||||
spawners_indestructible = noises.farness(p) > 0.7,
|
||||
-- spawners_indestructible = true,
|
||||
density_perchunk = 150 * Math.slopefromto(noises.farness(p), 0.3, 1)^2 * args.biter_base_density_scale,
|
||||
}
|
||||
end
|
||||
|
||||
IslandsCommon.enemies_1(args, spec)
|
||||
end
|
||||
|
||||
|
||||
-- function Public.break_rock(surface, p, entity_name)
|
||||
-- -- return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
-- end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
return Hunt.silo_setup_position(0.5)
|
||||
end
|
||||
|
||||
|
||||
return Public
|
83
maps/pirates/surfaces/islands/radioactive/data.lua
Normal file
83
maps/pirates/surfaces/islands/radioactive/data.lua
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Abandoned Labs'}
|
||||
|
||||
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},
|
||||
daynightcycletype = 4,
|
||||
min_brightness = 0.05,
|
||||
base_starting_treasure = 1000,
|
||||
base_starting_rock_material = 1200,
|
||||
base_starting_wood = 800,
|
||||
base_starting_treasure_maps = 1,
|
||||
default_decoratives = false,
|
||||
}
|
||||
|
||||
function Public.base_ores() --here, just for the gui:
|
||||
return {
|
||||
['copper-ore'] = 1,
|
||||
['coal'] = 1,
|
||||
['uranium-ore'] = 7,
|
||||
['stone'] = 5,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 200
|
||||
local hscale = 0.12
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1},
|
||||
{wavelength = 2.5, amplitude = rscale * 0.12},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'island1',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- {upperscale = 1000, amplitude = hscale * 200},
|
||||
{upperscale = 1600, amplitude = hscale * 1},
|
||||
{upperscale = 80, amplitude = hscale * 0.1},
|
||||
},
|
||||
},
|
||||
|
||||
forest = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 180, amplitude = 1},
|
||||
-- {upperscale = 0, amplitude = 0.15},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 110, amplitude = 1, seedfactor = 2},
|
||||
},
|
||||
},
|
||||
|
||||
ore = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 40, amplitude = 1, seedfactor = 3},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
return Public
|
310
maps/pirates/surfaces/islands/radioactive/radioactive.lua
Normal file
310
maps/pirates/surfaces/islands/radioactive/radioactive.lua
Normal file
@ -0,0 +1,310 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local Structures = require 'maps.pirates.structures.structures'
|
||||
local Common = require 'maps.pirates.common'
|
||||
-- local Effects = require 'maps.pirates.effects'
|
||||
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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.radioactive.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_1(args)
|
||||
ret.height_background = args.noise_generator.height_background
|
||||
ret.forest = args.noise_generator.forest
|
||||
ret.forest_abs = function (p) return Math.abs(ret.forest(p)) end
|
||||
ret.forest_abs_suppressed = function (p) return ret.forest_abs(p) - 1 * Math.slopefromto(ret.height(p), 0.17, 0.11) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.ore = args.noise_generator.ore
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
if noises.height(p) < 0.05 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
if (not args.iconized_generation) and noises.farness(p) > 0.02 and noises.farness(p) < 0.6 and Math.random(500) == 1 then
|
||||
args.specials[#args.specials + 1] = {name = 'buried-treasure', position = args.p}
|
||||
end
|
||||
else
|
||||
if Math.random() < Math.min(0.4,noises.height(p)) then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'white-desert-bush', position = p, amount = 1}
|
||||
elseif Math.random() > Math.max(0.8,1.2-noises.height(p)) then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'green-bush-mini', position = p, amount = 1}
|
||||
end
|
||||
if noises.height(p) < 0.33 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-2', position = args.p}
|
||||
elseif noises.height(p) < 0.35 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'dirt-5', position = args.p}
|
||||
else
|
||||
if noises.height_background(p) > 0.4 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'nuclear-ground', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'dirt-4', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) > 1 then
|
||||
local treedensity = 0.02 * Math.slopefromto(noises.forest_abs_suppressed(p), 1, 1.1)
|
||||
if noises.forest(p) > 1.4 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'dead-grey-trunk', position = args.p, visible_on_overworld = true} end
|
||||
elseif noises.forest(p) < -0.95 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'dry-tree', position = args.p, visible_on_overworld = true} end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.65 then
|
||||
if noises.height(p) > 0.12 then
|
||||
if noises.rock_abs(p) > 0.25 then
|
||||
local rockdensity = 1/200 * Math.slopefromto(noises.rock_abs(p), 0.25, 0.6)
|
||||
local rockrng = Math.random()
|
||||
if rockrng < rockdensity then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
elseif rockrng < rockdensity * 1.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-medium', position = args.p}
|
||||
elseif rockrng < rockdensity * 2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-small', position = args.p}
|
||||
elseif rockrng < rockdensity * 2.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-tiny', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.8 and noises.height(p) > 0.35 then
|
||||
if noises.ore(p) > 1 then
|
||||
args.entities[#args.entities + 1] = {name = 'uranium-ore', position = args.p, amount = 2000}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.8 and noises.height(p) < 0.35 and noises.height(p) > 0.05 then
|
||||
if noises.ore(p) < -1.5 then
|
||||
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}
|
||||
else
|
||||
args.entities[#args.entities + 1] = {name = 'copper-ore', position = args.p, amount = 100}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.farness(p) > 0.3,
|
||||
-- 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,
|
||||
}
|
||||
end
|
||||
|
||||
IslandsCommon.enemies_1(args, spec, true)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function Public.spawn_structures()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
-- local surface = game.surfaces[destination.surface_name]
|
||||
-- local subtype = destination.subtype
|
||||
-- local force = memory.force
|
||||
-- local ancient_force = string.format('ancient-friendly-%03d', memory.id)
|
||||
|
||||
local ps = Public.structure_positions()
|
||||
|
||||
if not destination.dynamic_data.structures_waiting_to_be_placed then
|
||||
destination.dynamic_data.structures_waiting_to_be_placed = {}
|
||||
end
|
||||
|
||||
for i = 1, #ps do
|
||||
local p = ps[i]
|
||||
|
||||
local structureData
|
||||
if i == 1 then
|
||||
structureData = Structures.IslandStructures.MATTISSO.small_radioactive_reactor.Data
|
||||
elseif i==2 then
|
||||
structureData = Structures.IslandStructures.MATTISSO.uranium_miners.Data
|
||||
elseif i>2 and i<7 then
|
||||
structureData = Structures.IslandStructures.MATTISSO.small_radioactive_centrifuge.Data
|
||||
else
|
||||
structureData = Structures.IslandStructures.MATTISSO.small_radioactive_lab.Data
|
||||
end
|
||||
|
||||
local special = {
|
||||
position = p,
|
||||
components = structureData.components,
|
||||
width = structureData.width,
|
||||
height = structureData.height,
|
||||
name = structureData.name,
|
||||
}
|
||||
destination.dynamic_data.structures_waiting_to_be_placed[#destination.dynamic_data.structures_waiting_to_be_placed + 1] = {data = special, tick = game.tick}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.structure_positions()
|
||||
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local width = destination.static_params.width
|
||||
local height = destination.static_params.height
|
||||
|
||||
local tries = 0
|
||||
local ret = {{x = 0, y = 0}}
|
||||
|
||||
local max_exclusion_distance = 45
|
||||
local maxtries = 2400
|
||||
|
||||
local args = {
|
||||
static_params = destination.static_params,
|
||||
noise_generator = Utils.noise_generator({}, 0),
|
||||
}
|
||||
|
||||
while #ret < 8 and tries < maxtries do
|
||||
|
||||
local p2
|
||||
if #ret == 1 then
|
||||
p2 = {x = island_center.x + Math.random(-35, 10), y = island_center.y + Math.random(-40, 40)}
|
||||
else
|
||||
p2 = {x = island_center.x + Math.random(Math.ceil(-width/2), Math.ceil(width/2)), y = island_center.y + Math.random(Math.ceil(-height/2), Math.ceil(height/2))}
|
||||
end
|
||||
|
||||
Common.ensure_chunks_at(surface, p2, 0.01)
|
||||
|
||||
local tile = surface.get_tile(p2)
|
||||
if tile and tile.valid and tile.name then
|
||||
if tile.name ~= 'sand-1' and tile.name ~= 'water' and tile.name ~= 'deepwater' then
|
||||
|
||||
local okay = true
|
||||
|
||||
local p3 = {x = p2.x + args.static_params.terraingen_coordinates_offset.x, y = p2.y + args.static_params.terraingen_coordinates_offset.y}
|
||||
local farness = IslandsCommon.island_farness_1(args)(p3)
|
||||
if (not okay) or (not (farness > 0.05 and farness < 0.55)) then
|
||||
okay = false
|
||||
end
|
||||
|
||||
local exclusion_distance = max_exclusion_distance * (maxtries - tries) / maxtries
|
||||
if #ret == 1 then exclusion_distance = 15 * (maxtries - tries) / maxtries end
|
||||
for _, p in pairs(ret) do
|
||||
if (not okay) or Math.distance(p, p2) < exclusion_distance then
|
||||
okay = false
|
||||
end
|
||||
end
|
||||
|
||||
if okay then
|
||||
ret[#ret + 1] = p2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tries = tries + 1
|
||||
end
|
||||
|
||||
if _DEBUG then
|
||||
log('radioactive world locations took ' .. tries .. ' tries.')
|
||||
end
|
||||
|
||||
if #ret < 8 then log('couldn\'t find four positions after 2400 tries') end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- function Public.break_rock(surface, p, entity_name)
|
||||
-- -- return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
-- end
|
||||
|
||||
|
||||
local function radioactive_tick()
|
||||
for _, id in pairs(Memory.get_global_memory().crew_active_ids) do
|
||||
Memory.set_working_id(id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
local tickinterval = 60
|
||||
|
||||
if destination.subtype == IslandsCommon.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)
|
||||
if (not destination.dynamic_data.evolution_accrued_time) then
|
||||
destination.dynamic_data.evolution_accrued_time = 0
|
||||
end
|
||||
destination.dynamic_data.evolution_accrued_time = destination.dynamic_data.evolution_accrued_time + extra_evo
|
||||
|
||||
if not memory.floating_pollution then memory.floating_pollution = 0 end
|
||||
|
||||
-- faster pollute:
|
||||
local pollution = 0
|
||||
local timer = destination.dynamic_data.timer
|
||||
if timer and timer > 15 then
|
||||
pollution = 4.9 * (6 * Common.difficulty()^(1.1) * (memory.overworldx/40)^(14/10) * (Balance.crew_scale())^(0.6)) / 3600 * tickinterval * (1 + (Common.difficulty()-1)*0.2 + 0.001 * timer)
|
||||
end
|
||||
|
||||
if pollution > 0 then
|
||||
memory.floating_pollution = memory.floating_pollution + pollution
|
||||
|
||||
game.pollution_statistics.on_flow('uranium-ore', pollution)
|
||||
end
|
||||
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
if surface and surface.valid and (not surface.freeze_daytime) and destination.dynamic_data.timer and destination.dynamic_data.timer >= CoreData.daynightcycle_types[Public.Data.static_params_default.daynightcycletype].ticksperday/60/2 then --once daytime, never go back to night
|
||||
surface.freeze_daytime = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.on_nth_tick(60, radioactive_tick)
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
89
maps/pirates/surfaces/islands/red_desert/data.lua
Normal file
89
maps/pirates/surfaces/islands/red_desert/data.lua
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Sandworm Caldera'}
|
||||
|
||||
Public.discord_emoji = CoreData.comfy_emojis.mjau
|
||||
|
||||
Public.terraingen_frame_width = 700
|
||||
Public.terraingen_frame_height = 700
|
||||
Public.static_params_default = {
|
||||
starting_time_of_day = 0,
|
||||
daynightcycletype = 1,
|
||||
default_decoratives = true,
|
||||
base_starting_treasure = 0,
|
||||
base_starting_rock_material = 8600,
|
||||
base_starting_wood = 600,
|
||||
}
|
||||
|
||||
function Public.base_ores() --here, just for the visualisation:
|
||||
return {
|
||||
['copper-ore'] = 5,
|
||||
['iron-ore'] = 5,
|
||||
['coal'] = 5,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 175
|
||||
local hscale = 0.16
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'island1',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- {upperscale = 1000, amplitude = hscale * 200},
|
||||
{upperscale = 1600, amplitude = hscale * 1},
|
||||
{upperscale = 60, amplitude = hscale * 0.15},
|
||||
},
|
||||
},
|
||||
|
||||
forest = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 100, amplitude = 1},
|
||||
},
|
||||
},
|
||||
|
||||
ore = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 40, amplitude = 1, seedfactor = 2},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 120, amplitude = 1, seedfactor = 3},
|
||||
},
|
||||
},
|
||||
|
||||
mood = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 200, amplitude = 70},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
435
maps/pirates/surfaces/islands/red_desert/red_desert.lua
Normal file
435
maps/pirates/surfaces/islands/red_desert/red_desert.lua
Normal file
@ -0,0 +1,435 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
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'
|
||||
local Effects = require 'maps.pirates.effects'
|
||||
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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.red_desert.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_1(args)
|
||||
ret.height_background = args.noise_generator.height_background
|
||||
ret.forest = args.noise_generator.forest
|
||||
ret.forest_abs = function (p) return Math.abs(ret.forest(p)) end
|
||||
ret.forest_abs_suppressed = function (p) return ret.forest_abs(p) - 1 * Math.slopefromto(ret.height(p), 0.17, 0.11) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.ore = args.noise_generator.ore
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.mood = args.noise_generator.mood
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
if noises.height(p) < 0.19 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
elseif noises.height(p) < 0.22 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'red-desert-3', position = args.p}
|
||||
else
|
||||
if noises.height_background(p) > 0.4 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'red-desert-2', position = args.p}
|
||||
elseif noises.height_background(p) > -0.15 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'red-desert-1', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'red-desert-0', position = args.p}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.height(p) > 0.32 then
|
||||
if noises.rock_abs(p) > 0.25 then
|
||||
|
||||
if noises.mood(p) < -0.5 then
|
||||
local density = 0.003 * Math.slopefromto(noises.rock_abs(p), 0.25, 0.4)
|
||||
local rng = Math.random()
|
||||
if rng < density then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'worms-decal', position = args.p}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.mood(p) < 0.1 then
|
||||
local rng = Math.random()
|
||||
if rng < 0.0004 then
|
||||
args.entities[#args.entities + 1] = {name = 'medium-remnants', position = args.p}
|
||||
elseif rng < 0.0007 then
|
||||
args.entities[#args.entities + 1] = {name = 'spidertron-remnants', position = args.p}
|
||||
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}
|
||||
elseif rng < 0.0014 then
|
||||
args.entities[#args.entities + 1] = {name = 'big-ship-wreck-1', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) > 0.85 then
|
||||
local treedensity = 0.3 * Math.slopefromto(noises.forest_abs_suppressed(p), 0.85, 0.9)
|
||||
if noises.forest(p) > 1.6 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'dry-hairy-tree', position = args.p, visible_on_overworld = true} end
|
||||
elseif noises.forest(p) < -0.95 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'dead-tree-desert', position = args.p, visible_on_overworld = true} end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.65 then
|
||||
if noises.height(p) > 0.15 then
|
||||
if noises.rock_abs(p) > 0.25 then
|
||||
local rockdensity = 1/200 * Math.slopefromto(noises.rock_abs(p), 0.25, 0.6)
|
||||
local rockrng = Math.random()
|
||||
if rockrng < rockdensity then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
elseif rockrng < rockdensity * 1.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-medium', position = args.p}
|
||||
elseif rockrng < rockdensity * 2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-small', position = args.p}
|
||||
elseif rockrng < rockdensity * 2.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-tiny', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.8 and noises.mood(p) > -0.3 then
|
||||
if noises.height(p) > 0.27 then
|
||||
if noises.ore(p) > 1.55 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 = 24}
|
||||
elseif noises.ore(p) < -1.6 then
|
||||
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 24}
|
||||
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}
|
||||
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}
|
||||
elseif noises.ore(p) < -2.1 then
|
||||
args.entities[#args.entities + 1] = {name = 'iron-ore', position = args.p, amount = 10}
|
||||
-- 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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
local rng = Math.random()
|
||||
local left_top = args.left_top
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.height(p) > 0.05 and noises.mood(p) > -0.6 and noises.farness(p) > 0.1,
|
||||
chanceper4chunks = 0.4,
|
||||
}
|
||||
end
|
||||
|
||||
-- initial attempt, to avoid placing two structures too close to each other, is to divide up the map into 2x2 chonks, and spawn once in each
|
||||
local bool1, bool2 = left_top.x % 64 < 32, left_top.y % 64 < 32
|
||||
local all_four_chunks = {
|
||||
{x = left_top.x, y = left_top.y},
|
||||
{x = left_top.x + (bool1 and 32 or -32), y = left_top.y},
|
||||
{x = left_top.x, y = left_top.y + (bool2 and 32 or -32)},
|
||||
{x = left_top.x + (bool1 and 32 or -32), y = left_top.y + (bool2 and 32 or -32)},
|
||||
}
|
||||
|
||||
if not args.other_map_generation_data.chunks_loaded then args.other_map_generation_data.chunks_loaded = {} end
|
||||
local chunks_loaded = args.other_map_generation_data.chunks_loaded
|
||||
|
||||
if not chunks_loaded[args.left_top.x] then chunks_loaded[args.left_top.x] = {} end
|
||||
chunks_loaded[args.left_top.x][args.left_top.y] = true
|
||||
|
||||
local nearby_chunks_generated_count = 0
|
||||
for i=1,4 do
|
||||
if chunks_loaded[all_four_chunks[i].x] and chunks_loaded[all_four_chunks[i].x][all_four_chunks[i].y] then
|
||||
nearby_chunks_generated_count = nearby_chunks_generated_count + 1
|
||||
end
|
||||
end
|
||||
|
||||
if nearby_chunks_generated_count == 4 then --should trigger only once per 4 chunks
|
||||
local avgleft_top = {
|
||||
x = (all_four_chunks[1].x + all_four_chunks[4].x)/2,
|
||||
y = (all_four_chunks[1].y + all_four_chunks[4].y)/2,
|
||||
}
|
||||
local leftmost_topmost = {
|
||||
x = avgleft_top.x - 32,
|
||||
y = avgleft_top.y - 32,
|
||||
}
|
||||
|
||||
local spec2 = spec{x = avgleft_top.x + 16, y = avgleft_top.y + 16}
|
||||
|
||||
if rng < spec2.chanceper4chunks then
|
||||
|
||||
local rng2 = Math.random()
|
||||
local struct
|
||||
|
||||
if rng2 < 28/100 then
|
||||
struct = Structures.IslandStructures.ROC.shelter2
|
||||
else
|
||||
struct = Structures.IslandStructures.ROC.shelter1
|
||||
end
|
||||
if struct then
|
||||
Structures.try_place(struct, args.specials, leftmost_topmost, 64, 64, function(p) return spec(p).placeable end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- function Public.break_rock(surface, p, entity_name)
|
||||
-- -- return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
-- end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
return Hunt.silo_setup_position()
|
||||
end
|
||||
|
||||
local function red_desert_tick()
|
||||
for _, id in pairs(Memory.get_global_memory().crew_active_ids) do
|
||||
Memory.set_working_id(id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if destination.subtype == IslandsCommon.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()
|
||||
|
||||
if game.tick % 360 == 0 and destination.dynamic_data.timer and destination.dynamic_data.timer > 60 then
|
||||
Public.custom_biter_ai()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.on_nth_tick(30, red_desert_tick)
|
||||
|
||||
|
||||
|
||||
function Public.underground_worms_ai()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
local player_force = memory.force
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
local evolution = memory.evolution_factor
|
||||
|
||||
if not destination.dynamic_data.worms_table then destination.dynamic_data.worms_table = {} end
|
||||
|
||||
local worms = destination.dynamic_data.worms_table
|
||||
|
||||
local indices_to_remove = {}
|
||||
|
||||
for i = #worms, 1, -1 do
|
||||
local w = worms[i]
|
||||
|
||||
w.age = w.age + 1
|
||||
-- despawn
|
||||
if w.age > w.max_age then
|
||||
indices_to_remove[#indices_to_remove + 1] = i
|
||||
else
|
||||
-- move
|
||||
w.position = {x = w.position.x + Balance.sandworm_speed() * 30/60 * w.direction.x, y = w.position.y + Balance.sandworm_speed() * 30/60 * w.direction.y}
|
||||
|
||||
if w.chart_tag then w.chart_tag.destroy() end
|
||||
|
||||
local tile = surface.get_tile(w.position.x, w.position.y)
|
||||
local on_land = tile and tile.valid and (not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name)) and (not Utils.contains(CoreData.noworm_tile_names, tile.name))
|
||||
|
||||
if on_land then
|
||||
local solid_ground = (tile and tile.valid and Utils.contains(CoreData.worm_solid_tile_names, tile.name))
|
||||
|
||||
-- stomp
|
||||
local big_bool = (w.age % 4 == 0)
|
||||
Effects.worm_movement_effect(surface, w.position, solid_ground, big_bool)
|
||||
|
||||
w.chart_tag = player_force.add_chart_tag(surface, {icon = {type = 'virtual', name = 'signal-red'}, position = w.position})
|
||||
|
||||
if not solid_ground then
|
||||
local nearby_characters = surface.find_entities_filtered{position = w.position, radius = 7, name = 'character'}
|
||||
|
||||
local character_outside = false
|
||||
for j = 1, #nearby_characters do
|
||||
local c = nearby_characters[j]
|
||||
|
||||
local t = surface.get_tile(c.position.x, c.position.y)
|
||||
if not (t and t.valid and Utils.contains(CoreData.worm_solid_tile_names, t.name))
|
||||
then
|
||||
character_outside = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if character_outside then
|
||||
local type = Common.get_random_worm_type(evolution)
|
||||
|
||||
local emerge_position = surface.find_non_colliding_position(type, w.position, 3, 0.5)
|
||||
|
||||
if emerge_position then
|
||||
local emerge_position_tile = surface.get_tile(emerge_position.x, emerge_position.y)
|
||||
|
||||
local can_emerge = (not solid_ground) and (not (tile and tile.valid and Utils.contains(CoreData.worm_solid_tile_names, emerge_position_tile.name)))
|
||||
|
||||
if can_emerge then
|
||||
surface.create_entity{name = type, position = emerge_position, force = enemy_force_name}
|
||||
Effects.worm_emerge_effect(surface, emerge_position)
|
||||
indices_to_remove[#indices_to_remove + 1] = i
|
||||
if w.chart_tag then w.chart_tag.destroy() end
|
||||
|
||||
local extra_evo = Balance.sandworm_evo_increase_per_spawn()
|
||||
Common.increment_evo(extra_evo)
|
||||
|
||||
if destination.dynamic_data then
|
||||
destination.dynamic_data.evolution_accrued_sandwurms = destination.dynamic_data.evolution_accrued_sandwurms + extra_evo
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #indices_to_remove do
|
||||
local index = indices_to_remove[i]
|
||||
|
||||
for j = index, #worms-1 do
|
||||
worms[j] = worms[j+1]
|
||||
end
|
||||
worms[#worms] = nil
|
||||
end
|
||||
|
||||
local max_worms = Math.ceil(45 * Math.sloped(Common.difficulty(), 1/2))
|
||||
|
||||
-- spawn worms
|
||||
if game.tick % 90 == 0 then
|
||||
if #worms < max_worms then
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local r = Math.max(destination.static_params.width, destination.static_params.height)/2
|
||||
|
||||
local theta = Math.random()*5.75 - Math.pi/2+0.25
|
||||
local p = {x = island_center.x + r*Math.sin(theta), y = island_center.y + r*Math.cos(theta)}
|
||||
|
||||
local theta2 = Math.random()*1.4-0.7
|
||||
local d = {x = -Math.sin(theta+theta2), y = -Math.cos(theta+theta2)}
|
||||
|
||||
worms[#worms + 1] = {position = p, direction = d, age = 0, max_age = 2*r/(Balance.sandworm_speed() * 30/60) * Math.cos(theta2/2)}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.custom_biter_ai()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
-- local difficulty = memory.difficulty
|
||||
local enemy_force_name = memory.enemy_force_name
|
||||
local evolution = memory.evolution_factor
|
||||
|
||||
local fraction_of_floating_pollution = 1/2
|
||||
local minimum_avg_units = 30
|
||||
local maximum_units = 256
|
||||
|
||||
local pollution_available = memory.floating_pollution
|
||||
local budget = fraction_of_floating_pollution * pollution_available
|
||||
|
||||
if budget >= minimum_avg_units * Common.averageUnitPollutionCost(evolution) then
|
||||
local initialbudget = budget
|
||||
|
||||
local position = Hunt.position_away_from_players_1({static_params = destination.static_params}, 50)
|
||||
|
||||
local units_created_count = 0
|
||||
local units_created = {}
|
||||
|
||||
local name = Common.get_random_unit_type(evolution)
|
||||
local unittype_pollutioncost = CoreData.biterPollutionValues[name] * 1.1 * Balance.scripted_biters_pollution_cost_multiplier()
|
||||
|
||||
local function spawn(name2)
|
||||
units_created_count = units_created_count + 1
|
||||
|
||||
local p = surface.find_non_colliding_position(name2, position, 50, 2)
|
||||
if not p then return end
|
||||
|
||||
local biter = surface.create_entity({name = name2, force = enemy_force_name, position = p})
|
||||
|
||||
units_created[#units_created + 1] = biter
|
||||
memory.scripted_biters[biter.unit_number] = {entity = biter, created_at = game.tick}
|
||||
|
||||
return biter.unit_number
|
||||
end
|
||||
|
||||
local whilesafety = 1000
|
||||
while units_created_count < maximum_units and budget >= unittype_pollutioncost and #memory.scripted_biters < CoreData.total_max_biters and whilesafety > 0 do
|
||||
whilesafety = whilesafety - 1
|
||||
pollution_available = pollution_available - unittype_pollutioncost
|
||||
budget = budget - unittype_pollutioncost
|
||||
spawn(name)
|
||||
end
|
||||
|
||||
game.pollution_statistics.on_flow(name, budget - initialbudget)
|
||||
memory.floating_pollution = pollution_available
|
||||
|
||||
if (not units_created) or (not #units_created) or (#units_created == 0) then return end
|
||||
|
||||
Effects.biters_emerge(surface, position)
|
||||
|
||||
local position2 = surface.find_non_colliding_position('rocket-silo', position, 256, 2) or position
|
||||
|
||||
local unit_group = surface.create_unit_group({position = position2, force = enemy_force_name})
|
||||
for _, unit in pairs(units_created) do
|
||||
unit_group.add_member(unit)
|
||||
end
|
||||
memory.scripted_unit_groups[unit_group.group_number] = {ref = unit_group, script_type = 'burrowed'}
|
||||
|
||||
local target = {valid = true, position = {x = memory.boat.position.x - 60, y = memory.boat.position.y} or nil, name = 'boatarea'}
|
||||
|
||||
unit_group.set_command{
|
||||
type = defines.command.attack_area,
|
||||
destination = target.position,
|
||||
radius = 30,
|
||||
distraction = defines.distraction.by_anything
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
85
maps/pirates/surfaces/islands/standard/data.lua
Normal file
85
maps/pirates/surfaces/islands/standard/data.lua
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Isle of Buried Treasure'}
|
||||
|
||||
Public.terraingen_frame_width = 896
|
||||
Public.terraingen_frame_height = 896
|
||||
Public.static_params_default = {
|
||||
default_decoratives = true,
|
||||
base_starting_treasure = 1000,
|
||||
base_starting_rock_material = 800,
|
||||
base_starting_wood = 1200,
|
||||
base_starting_treasure_maps = 6,
|
||||
starting_time_of_day = 0,
|
||||
daynightcycletype = 3,
|
||||
brightness_visual_weights = {0.12, 0.12, 0.12}, --light night, but still workable without lights
|
||||
min_brightness = 0.2,
|
||||
}
|
||||
|
||||
function Public.base_ores()
|
||||
return {
|
||||
['copper-ore'] = 0.9,
|
||||
['iron-ore'] = 5.7,
|
||||
['coal'] = 4,
|
||||
['stone'] = 1.0,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 250
|
||||
local hscale = 0.1
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1},
|
||||
{wavelength = 1.6, amplitude = rscale * 0.3},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'island1',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- {upperscale = 1000, amplitude = hscale * 200},
|
||||
{upperscale = 1600, amplitude = hscale * 1},
|
||||
{upperscale = 80, amplitude = hscale * 0.1},
|
||||
},
|
||||
},
|
||||
|
||||
forest = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 180, amplitude = 1},
|
||||
-- {upperscale = 0, amplitude = 0.15},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 110, amplitude = 1, seedfactor = 2},
|
||||
},
|
||||
},
|
||||
|
||||
mood = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 250, amplitude = 70},
|
||||
{wavelength = 50, amplitude = 20},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
147
maps/pirates/surfaces/islands/standard/standard.lua
Normal file
147
maps/pirates/surfaces/islands/standard/standard.lua
Normal file
@ -0,0 +1,147 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- 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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.standard.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_1(args)
|
||||
ret.forest = args.noise_generator.forest
|
||||
ret.forest_abs = function (p) return Math.abs(ret.forest(p)) end
|
||||
ret.forest_abs_suppressed = function (p) return ret.forest_abs(p) - 1 * Math.slopefromto(ret.height(p), 0.17, 0.11) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.mood = args.noise_generator.mood
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
if noises.height(p) < 0.05 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
if (not args.iconized_generation) and noises.farness(p) > 0.02 and noises.farness(p) < 0.6 and Math.random(500) == 1 then
|
||||
args.specials[#args.specials + 1] = {name = 'buried-treasure', position = args.p}
|
||||
end
|
||||
elseif noises.height(p) < 0.12 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-2', position = args.p}
|
||||
else
|
||||
if noises.forest_abs_suppressed(p) > 0.3 and noises.rock(p) < 0.3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'dry-dirt', position = args.p}
|
||||
elseif noises.forest_abs_suppressed(p) > 0.15 and noises.rock(p) < 0.3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'dirt-3', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'dirt-2', position = args.p}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.height(p) > 0.06 then
|
||||
if noises.forest_abs_suppressed(p) > 0.5 then
|
||||
if (not args.iconized_generation) and noises.forest_abs_suppressed(p) < 0.75 and Math.random(2000) == 1 then
|
||||
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
|
||||
else
|
||||
local forest_noise = noises.forest(p)
|
||||
local treedensity = 0.7 * Math.slopefromto(noises.forest_abs_suppressed(p), 0.5, 0.7)
|
||||
if forest_noise > 0 then
|
||||
if noises.rock(p) > 0 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-06', position = args.p, visible_on_overworld = true} end
|
||||
else
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-06-brown', position = args.p} end
|
||||
end
|
||||
elseif forest_noise < -1 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-03', position = args.p, visible_on_overworld = true} end
|
||||
else
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-07', position = args.p} end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.45 then
|
||||
|
||||
if noises.height(p) > 0.12 then
|
||||
if noises.rock_abs(p) > 0.22 then
|
||||
local rockdensity = 1/600 * Math.slopefromto(noises.rock_abs(p), 0.22, 0.6) + 1/5 * Math.slopefromto(noises.rock_abs(p), 2.4, 2.6)
|
||||
local rockrng = Math.random()
|
||||
if rockrng < rockdensity then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
elseif rockrng < rockdensity * 1.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-medium', position = args.p}
|
||||
elseif rockrng < rockdensity * 2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-small', position = args.p}
|
||||
elseif rockrng < rockdensity * 2.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-tiny', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.height(p) > 0.18 and noises.mood(p) > 0.6 then
|
||||
if noises.forest_abs(p) < 0.2 and noises.rock_abs(p) > 1.5 then
|
||||
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 7}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.farness(p) > 0.3,
|
||||
-- spawners_indestructible = noises.farness(p) > 0.7,
|
||||
spawners_indestructible = false,
|
||||
density_perchunk = 30 * Math.slopefromto(noises.mood(p), 0.14, -0.1) * Math.slopefromto(noises.farness(p), 0.3, 1)^2 * args.biter_base_density_scale,
|
||||
}
|
||||
end
|
||||
|
||||
IslandsCommon.enemies_1(args, spec)
|
||||
|
||||
local spec2 = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.height(p) >= 0 and noises.forest_abs_suppressed(p) < 0.3 + Math.max(0, 0.2 - noises.height(p)),
|
||||
chanceper4chunks = 0.5 * Math.slopefromto(noises.farness(p), 0.1, 0.4) * Math.slopefromto(noises.mood(p), 0, 0.25),
|
||||
}
|
||||
end
|
||||
IslandsCommon.assorted_structures_1(args, spec2)
|
||||
end
|
||||
|
||||
|
||||
-- function Public.break_rock(surface, p, entity_name)
|
||||
-- -- return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
-- end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
return Hunt.silo_setup_position()
|
||||
end
|
||||
|
||||
|
||||
return Public
|
85
maps/pirates/surfaces/islands/standard_variant/data.lua
Normal file
85
maps/pirates/surfaces/islands/standard_variant/data.lua
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Secluded Dells'}
|
||||
|
||||
Public.terraingen_frame_width = 896
|
||||
Public.terraingen_frame_height = 896
|
||||
Public.static_params_default = {
|
||||
default_decoratives = true,
|
||||
base_starting_treasure = 1000,
|
||||
base_starting_rock_material = 800,
|
||||
base_starting_wood = 1200,
|
||||
base_starting_treasure_maps = 1,
|
||||
starting_time_of_day = 0,
|
||||
daynightcycletype = 3,
|
||||
brightness_visual_weights = {0.12, 0.12, 0.12}, --light night, but still workable without lights
|
||||
min_brightness = 0.2,
|
||||
}
|
||||
|
||||
function Public.base_ores()
|
||||
return {
|
||||
['copper-ore'] = 4.4,
|
||||
['iron-ore'] = 4.9,
|
||||
['coal'] = 4,
|
||||
['stone'] = 1.2,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 220
|
||||
local hscale = 0.1
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1},
|
||||
{wavelength = 1.6, amplitude = rscale * 0.25},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'island1',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- {upperscale = 1000, amplitude = hscale * 200},
|
||||
{upperscale = 1600, amplitude = hscale * 1},
|
||||
{upperscale = 80, amplitude = hscale * 0.1},
|
||||
},
|
||||
},
|
||||
|
||||
forest = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 75, amplitude = 1},
|
||||
-- {upperscale = 0, amplitude = 0.15},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 110, amplitude = 1, seedfactor = 2},
|
||||
},
|
||||
},
|
||||
|
||||
mood = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 250, amplitude = 70},
|
||||
{wavelength = 50, amplitude = 20},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
@ -0,0 +1,151 @@
|
||||
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
-- local Structures = require 'maps.pirates.structures.structures'
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- 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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.standard_variant.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_1(args)
|
||||
ret.forest = args.noise_generator.forest
|
||||
ret.forest_abs = function (p) return Math.abs(ret.forest(p)) end
|
||||
ret.forest_abs_suppressed = function (p) return ret.forest_abs(p) - 1 * Math.slopefromto(ret.height(p), 0.17, 0.11) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.mood = args.noise_generator.mood
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
if noises.height(p) < 0.04 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-1', position = args.p}
|
||||
if (not args.iconized_generation) and noises.farness(p) > 0.02 and noises.farness(p) < 0.6 and Math.random(500) == 1 then
|
||||
args.specials[#args.specials + 1] = {name = 'buried-treasure', position = args.p}
|
||||
end
|
||||
elseif noises.height(p) < 0.05 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'sand-2', position = args.p}
|
||||
elseif noises.height(p) < 0.11 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'dry-dirt', position = args.p}
|
||||
elseif noises.height(p) < 0.12 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-4', position = args.p}
|
||||
else
|
||||
if noises.forest_abs_suppressed(p) > 0.3 and noises.rock(p) < 0.3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'dirt-7', position = args.p}
|
||||
elseif noises.forest_abs_suppressed(p) > 0.15 and noises.rock(p) < 0.3 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-4', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-3', position = args.p}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.height(p) > 0.11 then
|
||||
if noises.forest_abs_suppressed(p) > 0.7 then
|
||||
if (not args.iconized_generation) and noises.forest_abs_suppressed(p) < 1 and Math.random(750) == 1 then -- high amounts of this
|
||||
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
|
||||
else
|
||||
local forest_noise = noises.forest(p)
|
||||
local treedensity = 0.7 * Math.slopefromto(noises.forest_abs_suppressed(p), 0.61, 0.76)
|
||||
if forest_noise > 0 then
|
||||
if noises.rock(p) > 0.05 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-08-red', position = args.p, visible_on_overworld = true} end
|
||||
elseif noises.rock(p) < -0.05 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-09-brown', position = args.p} end
|
||||
end
|
||||
elseif forest_noise < -1.2 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-09', position = args.p, visible_on_overworld = true} end
|
||||
else
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-02-red', position = args.p} end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.45 then
|
||||
|
||||
if noises.height(p) > 0.12 then
|
||||
if noises.rock_abs(p) > 0.25 then
|
||||
local rockdensity = 1/600 * Math.slopefromto(noises.rock_abs(p), 0.25, 0.6) + 1/5 * Math.slopefromto(noises.rock_abs(p), 2.4, 2.6)
|
||||
local rockrng = Math.random()
|
||||
if rockrng < rockdensity then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
elseif rockrng < rockdensity * 1.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-medium', position = args.p}
|
||||
elseif rockrng < rockdensity * 2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-small', position = args.p}
|
||||
elseif rockrng < rockdensity * 2.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-tiny', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if noises.height(p) > 0.18 and noises.mood(p) > 0.3 then
|
||||
if noises.forest_abs(p) < 0.2 and noises.rock_abs(p) > 1.5 then
|
||||
args.entities[#args.entities + 1] = {name = 'coal', position = args.p, amount = 7}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.farness(p) > 0.3,
|
||||
spawners_indestructible = false,
|
||||
-- spawners_indestructible = noises.farness(p) > 0.7,
|
||||
density_perchunk = 25 * Math.slopefromto(noises.mood(p), 0.16, -0.1) * Math.slopefromto(noises.farness(p), 0.3, 1)^2 * args.biter_base_density_scale,
|
||||
}
|
||||
end
|
||||
|
||||
IslandsCommon.enemies_1(args, spec)
|
||||
|
||||
local spec2 = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.height(p) >= 0 and noises.forest_abs_suppressed(p) < 0.3 + Math.max(0, 0.2 - noises.height(p)),
|
||||
chanceper4chunks = 0.5 * Math.slopefromto(noises.farness(p), 0.1, 0.4) * Math.slopefromto(noises.mood(p), 0, 0.25),
|
||||
}
|
||||
end
|
||||
IslandsCommon.assorted_structures_1(args, spec2)
|
||||
end
|
||||
|
||||
|
||||
-- function Public.break_rock(surface, p, entity_name)
|
||||
-- -- return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
-- end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
return Hunt.silo_setup_position()
|
||||
end
|
||||
|
||||
|
||||
return Public
|
89
maps/pirates/surfaces/islands/swamp/data.lua
Normal file
89
maps/pirates/surfaces/islands/swamp/data.lua
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Poisonous Fen'}
|
||||
|
||||
Public.terraingen_frame_width = 325
|
||||
Public.terraingen_frame_height = 325
|
||||
Public.static_params_default = {
|
||||
starting_time_of_day = 0.35,
|
||||
daynightcycletype = 1,
|
||||
brightness_visual_weights = {0, 0, 0},
|
||||
default_decoratives = true,
|
||||
base_starting_treasure = 1000,
|
||||
base_starting_rock_material = 800,
|
||||
base_starting_wood = 1200,
|
||||
base_starting_treasure_maps = 0,
|
||||
}
|
||||
|
||||
function Public.base_ores()
|
||||
return {
|
||||
['copper-ore'] = 2.9,
|
||||
['iron-ore'] = 3.6,
|
||||
['coal'] = 4.8,
|
||||
['stone'] = 0.5,
|
||||
['crude-oil'] = 80,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 170
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1},
|
||||
{wavelength = 2, amplitude = rscale * 0.2},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'island1',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- {upperscale = 1000, amplitude = hscale * 200},
|
||||
{upperscale = 600, amplitude = 0.1},
|
||||
},
|
||||
},
|
||||
|
||||
forest = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 70, amplitude = 1},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'forest1',
|
||||
normalised = true,
|
||||
params = {
|
||||
{upperscale = 120, amplitude = 1, seedfactor = 2},
|
||||
},
|
||||
},
|
||||
|
||||
mood = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 250, amplitude = 70},
|
||||
{wavelength = 50, amplitude = 20},
|
||||
},
|
||||
},
|
||||
|
||||
terrain = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 48, amplitude = 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
return Public
|
231
maps/pirates/surfaces/islands/swamp/swamp.lua
Normal file
231
maps/pirates/surfaces/islands/swamp/swamp.lua
Normal file
@ -0,0 +1,231 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local Balance = require 'maps.pirates.balance'
|
||||
local Structures = require 'maps.pirates.structures.structures'
|
||||
local Common = require 'maps.pirates.common'
|
||||
-- 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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.swamp.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_1(args)
|
||||
ret.forest = args.noise_generator.forest
|
||||
ret.forest_abs = function (p) return Math.abs(ret.forest(p)) end
|
||||
ret.forest_abs_suppressed = function (p) return ret.forest_abs(p) - 1 * Math.slopefromto(ret.height(p), 0.35, 0.1) end
|
||||
ret.terrain = args.noise_generator.terrain
|
||||
ret.terrain_abs = function (p) return Math.abs(ret.terrain(p)) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.mood = args.noise_generator.mood
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function Public.terrain(args)
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water', position = args.p}
|
||||
return
|
||||
end
|
||||
|
||||
local land = true
|
||||
|
||||
if noises.height(p) < 0.03 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water-shallow', position = args.p}
|
||||
land = false
|
||||
-- elseif noises.height(p) < 0.07 then
|
||||
-- args.tiles[#args.tiles + 1] = {name = 'grass-4', position = args.p}
|
||||
else
|
||||
if noises.terrain(p) < 0.44 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-1', position = args.p}
|
||||
elseif noises.terrain(p) < 0.59 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'grass-2', position = args.p}
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'water-mud', position = args.p}
|
||||
land = false
|
||||
end
|
||||
end
|
||||
|
||||
if land then
|
||||
if (not args.iconized_generation) and Math.random(2500) == 1 then
|
||||
args.specials[#args.specials + 1] = {name = 'chest', position = args.p}
|
||||
else
|
||||
if noises.forest_abs(p) > 0.15 then
|
||||
local treedensity = 0.08 * Math.slopefromto(noises.forest_abs_suppressed(p), 0.3, 0.6) + 0.3 * Math.slopefromto(noises.forest_abs_suppressed(p), 0.65, 1.0)
|
||||
if noises.forest(p) > 1.3 then
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-09-brown', position = args.p} end
|
||||
else
|
||||
if Math.random(1,100) < treedensity*100 then args.entities[#args.entities + 1] = {name = 'tree-08', position = args.p, visible_on_overworld = true} end
|
||||
end
|
||||
|
||||
if noises.forest_abs_suppressed(p) < 0.7 then
|
||||
|
||||
if noises.height(p) > 0.12 then
|
||||
if noises.rock_abs(p) > -0.15 then
|
||||
local rockdensity = 1/600 * Math.slopefromto(noises.rock_abs(p), 0.22, 0.6) + 1/5 * Math.slopefromto(noises.rock_abs(p), 1.6, 1.8)
|
||||
local rockrng = Math.random()
|
||||
if rockrng < rockdensity then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(args.p)
|
||||
elseif rockrng < rockdensity * 1.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-medium', position = args.p}
|
||||
elseif rockrng < rockdensity * 2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-small', position = args.p}
|
||||
elseif rockrng < rockdensity * 2.5 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'rock-tiny', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if noises.mood(p) > 0.3 then
|
||||
local density = 0.001 * Math.slopefromto(noises.rock_abs(p), 0.25, 0.4)
|
||||
local rng = Math.random()
|
||||
if rng < density then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'shroom-decal', position = args.p}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.mood(p) < -0.3 then
|
||||
local rng = Math.random()
|
||||
if rng < 0.0015 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'lichen-decal', position = args.p}
|
||||
end
|
||||
end
|
||||
|
||||
local rng = Math.random()
|
||||
if rng < 0.004 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'green-asterisk', position = args.p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.farness(p) > 0.3,
|
||||
-- spawners_indestructible = noises.farness(p) > 0.75,
|
||||
spawners_indestructible = false,
|
||||
spawners_density_perchunk = 100 * Math.slopefromto(noises.mood(p), 0.7, 0.5) * Math.slopefromto(noises.farness(p), 0.35, 1)^2 * args.biter_base_density_scale,
|
||||
worms_density_perchunk = 60 * Math.slopefromto(noises.mood(p), 0.7, 0.5) * Math.slopefromto(noises.farness(p), 0.25, 1)^2 * args.biter_base_density_scale,
|
||||
}
|
||||
end
|
||||
|
||||
IslandsCommon.enemies_specworms_separate(args, spec)
|
||||
|
||||
local spec2 = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.height(p) > 0.05,
|
||||
chanceperchunk = 0.25 * Math.slopefromto(noises.farness(p), 0.05, 0.15),
|
||||
}
|
||||
end
|
||||
Public.swamp_structures(args, spec2)
|
||||
end
|
||||
|
||||
|
||||
function Public.swamp_structures(args, spec)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
-- local overworldx = memory.overworldx or 0
|
||||
|
||||
local rng = Math.random()
|
||||
local left_top = args.left_top
|
||||
|
||||
local spec2 = spec{x = left_top.x + 16, y = left_top.y + 16}
|
||||
|
||||
if rng < spec2.chanceperchunk then
|
||||
|
||||
local struct
|
||||
struct = Structures.IslandStructures.ROC.swamp_lonely_storage_tank
|
||||
|
||||
if struct then
|
||||
Structures.try_place(struct, args.specials, left_top, 64, 64, function(p) return spec(p).placeable end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.break_rock(surface, p, entity_name)
|
||||
return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
return Hunt.silo_setup_position()
|
||||
end
|
||||
|
||||
|
||||
local function swamp_tick()
|
||||
for _, id in pairs(Memory.get_global_memory().crew_active_ids) do
|
||||
Memory.set_working_id(id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if destination.subtype and destination.subtype == IslandsCommon.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
|
||||
|
||||
local island_center = destination.static_params.islandcenter_position
|
||||
local width = destination.static_params.width
|
||||
local height = destination.static_params.height
|
||||
|
||||
local area = width*height
|
||||
|
||||
local period = 5 * Math.ceil(7 / (area/(330*330)))
|
||||
|
||||
if game.tick % period == 0 then
|
||||
local random_x = Math.random(island_center.x - width/2, island_center.x + width/2)
|
||||
local random_y = Math.random(island_center.y - height/2, island_center.y + height/2)
|
||||
local random_p = {x = random_x, y = random_y}
|
||||
|
||||
local tile = surface.get_tile(random_x, random_y)
|
||||
if not (tile and tile.valid) then return end
|
||||
|
||||
if tile.name == 'water-mud' then
|
||||
local nearby_characters = surface.find_entities_filtered{position = random_p, radius = 66, name = 'character'}
|
||||
local nearby_characters_count = #nearby_characters
|
||||
if nearby_characters_count >= 1 then
|
||||
Common.create_poison_clouds(surface, random_p)
|
||||
if Math.random(1, 3) == 1 then
|
||||
local random_angles = {Math.rad(Math.random(359))}
|
||||
Common.create_poison_clouds(surface, {x = random_x + 24 * Math.cos(random_angles[1]), y = random_y + 24 * Math.sin(random_angles[1])})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.on_nth_tick(5, swamp_tick)
|
||||
|
||||
|
||||
return Public
|
92
maps/pirates/surfaces/islands/walkways/data.lua
Normal file
92
maps/pirates/surfaces/islands/walkways/data.lua
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
-- local Common = require 'maps.pirates.common'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
-- local Math = require 'maps.pirates.math'
|
||||
|
||||
local Public = {}
|
||||
|
||||
Public.display_names = {'Frozen Pools'}
|
||||
|
||||
Public.terraingen_frame_width = 896
|
||||
Public.terraingen_frame_height = 896
|
||||
Public.static_params_default = {
|
||||
starting_time_of_day = 0,
|
||||
daynightcycletype = 4,
|
||||
min_brightness = 0.05,
|
||||
brightness_visual_weights = {1, 1, 1}, --almost pitch black
|
||||
default_decoratives = false,
|
||||
base_starting_rock_material = 800,
|
||||
}
|
||||
|
||||
function Public.base_ores()
|
||||
return {
|
||||
['copper-ore'] = 2.6,
|
||||
['iron-ore'] = 2.8,
|
||||
['coal'] = 4,
|
||||
['crude-oil'] = 120,
|
||||
}
|
||||
end
|
||||
|
||||
local rscale = 135
|
||||
local hscale = 1/100
|
||||
Public.noiseparams = {
|
||||
radius = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 0, amplitude = rscale * 1.0},
|
||||
{wavelength = 2.5, amplitude = rscale * 0.23},
|
||||
},
|
||||
},
|
||||
|
||||
height_background = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
-- shape:
|
||||
{wavelength = 1600, amplitude = hscale * 22},
|
||||
{wavelength = 800, amplitude = hscale * 18},
|
||||
{wavelength = 400, amplitude = hscale * 15},
|
||||
{wavelength = 300, amplitude = hscale * 11},
|
||||
{wavelength = 200, amplitude = hscale * 8},
|
||||
{wavelength = 140, amplitude = hscale * 6},
|
||||
{wavelength = 100, amplitude = hscale * 4},
|
||||
-- edges:
|
||||
{wavelength = 60, amplitude = hscale * 2.5},
|
||||
{wavelength = 30, amplitude = hscale * 1.5},
|
||||
{wavelength = 9, amplitude = hscale * 0.5}
|
||||
},
|
||||
},
|
||||
|
||||
walkways = {
|
||||
type = 'simplex_2d',
|
||||
normalised = false,
|
||||
params = {
|
||||
{wavelength = 300, amplitude = 15/100},
|
||||
{wavelength = 65, amplitude = 90/100},
|
||||
{wavelength = 7, amplitude = 5/100},
|
||||
},
|
||||
},
|
||||
|
||||
rock = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 100, amplitude = 80},
|
||||
{wavelength = 50, amplitude = 20},
|
||||
{wavelength = 6, amplitude = 20},
|
||||
},
|
||||
},
|
||||
|
||||
mood = {
|
||||
type = 'simplex_2d',
|
||||
normalised = true,
|
||||
params = {
|
||||
{wavelength = 250, amplitude = 70},
|
||||
{wavelength = 50, amplitude = 20},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
return Public
|
158
maps/pirates/surfaces/islands/walkways/walkways.lua
Normal file
158
maps/pirates/surfaces/islands/walkways/walkways.lua
Normal file
@ -0,0 +1,158 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- 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'
|
||||
-- local Utils = require 'maps.pirates.utils_local'
|
||||
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 Hunt = require 'maps.pirates.surfaces.islands.hunt'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.walkways.data'
|
||||
|
||||
|
||||
function Public.noises(args)
|
||||
local ret = {}
|
||||
|
||||
ret.height = IslandsCommon.island_height_1(args)
|
||||
ret.walkways = function (p) return Math.abs(args.noise_generator.walkways(p)) end
|
||||
ret.rock = args.noise_generator.rock
|
||||
ret.rock_abs = function (p) return Math.abs(ret.rock(p)) end
|
||||
ret.mood = args.noise_generator.mood
|
||||
ret.farness = IslandsCommon.island_farness_1(args) --isn't available on the iconized pass, only on actual generation; check args.iconized_generation before you use this
|
||||
return ret
|
||||
end
|
||||
|
||||
function Public.terrain(args)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local noises = Public.noises(args)
|
||||
local p = args.p
|
||||
|
||||
if IslandsCommon.place_water_tile(args) then return end
|
||||
|
||||
if noises.height(p) < 0.05 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'water-mud', position = p}
|
||||
|
||||
elseif noises.height(p) < 0.1 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'landfill', position = p}
|
||||
if Math.random() < 1/50 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'brown-asterisk', position = p, amount = 1}
|
||||
end
|
||||
else
|
||||
if noises.walkways(p) < 0.34 then
|
||||
args.tiles[#args.tiles + 1] = {name = 'landfill', position = p}
|
||||
|
||||
|
||||
if noises.walkways(p) <= 0.01 then
|
||||
if Math.random(40) == 1 then
|
||||
args.entities[#args.entities + 1] = {name = 'big-scorchmark-tintable', position = p}
|
||||
end
|
||||
elseif noises.walkways(p) <= 0.02 then
|
||||
if Math.random(40) == 1 then
|
||||
args.entities[#args.entities + 1] = {name = 'medium-scorchmark-tintable', position = p}
|
||||
end
|
||||
end
|
||||
|
||||
if Math.abs(noises.rock(p)) < 0.3 then
|
||||
if Math.random() < 1/20 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'red-pita', position = p, amount = 1}
|
||||
end
|
||||
end
|
||||
|
||||
if noises.rock(p) > 0.2 then
|
||||
if Math.random() < (0.25 - noises.walkways(p))/8 then
|
||||
args.entities[#args.entities + 1] = IslandsCommon.random_rock_1(p)
|
||||
end
|
||||
elseif Math.random() < -(noises.rock(p) + 0.3)/2 then
|
||||
args.decoratives[#args.decoratives + 1] = {name = 'red-croton', position = p, amount = 1}
|
||||
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}
|
||||
end
|
||||
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'water-shallow', position = p}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.chunk_structures(args)
|
||||
|
||||
local spec = function(p)
|
||||
local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
return {
|
||||
placeable = noises.walkways(p) < 0.30,
|
||||
density_perchunk = 20 * (noises.farness(p) - 0.1)^3 * args.biter_base_density_scale,
|
||||
spawners_indestructible = true,
|
||||
}
|
||||
end
|
||||
IslandsCommon.enemies_1(args, spec)
|
||||
|
||||
-- local spec2 = function(p)
|
||||
-- local noises = Public.noises{p = p, noise_generator = args.noise_generator, static_params = args.static_params, seed = args.seed}
|
||||
|
||||
-- return {
|
||||
-- placeable = noises.height(p) > 0.1 and noises.walkways(p) < 0.3,
|
||||
-- chanceper4chunks = 1/2,
|
||||
-- }
|
||||
-- end
|
||||
-- IslandsCommon.assorted_structures_1(args, spec2)
|
||||
end
|
||||
|
||||
|
||||
function Public.generate_silo_setup_position()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
local surface = game.surfaces[destination.surface_name]
|
||||
|
||||
local p_silo = Hunt.silo_setup_position(0.2)
|
||||
|
||||
local tiles = {}
|
||||
for x = -6.5, 6.5, 1 do
|
||||
for y = -6.5, 6.5, 1 do
|
||||
tiles[#tiles + 1] = {name = CoreData.world_concrete_tile, position = {x = p_silo.x + x, y = p_silo.y + y}}
|
||||
end
|
||||
end
|
||||
Common.ensure_chunks_at(surface, p_silo, 1)
|
||||
surface.set_tiles(tiles, true)
|
||||
|
||||
return p_silo
|
||||
end
|
||||
|
||||
|
||||
function Public.break_rock(surface, p, entity_name)
|
||||
return Ores.try_ore_spawn(surface, p, entity_name)
|
||||
end
|
||||
|
||||
|
||||
local function walkways_tick()
|
||||
for _, id in pairs(Memory.get_global_memory().crew_active_ids) do
|
||||
Memory.set_working_id(id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local destination = Common.current_destination()
|
||||
|
||||
if destination.subtype and destination.subtype == IslandsCommon.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')
|
||||
if not (player.character and player.character.valid) then
|
||||
Common.notify_force(player.force, player.name .. ' froze to death.')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.on_nth_tick(20, walkways_tick)
|
||||
|
||||
|
||||
return Public
|
143
maps/pirates/surfaces/lobby.lua
Normal file
143
maps/pirates/surfaces/lobby.lua
Normal file
File diff suppressed because one or more lines are too long
297
maps/pirates/surfaces/sea/kraken.lua
Normal file
297
maps/pirates/surfaces/sea/kraken.lua
Normal file
@ -0,0 +1,297 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
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 Structures = require 'maps.pirates.structures.structures'
|
||||
local Token = require 'utils.token'
|
||||
local Task = require 'utils.task'
|
||||
-- local SurfacesCommon = require 'maps.pirates.surfaces.common'
|
||||
local Effects = require 'maps.pirates.effects'
|
||||
|
||||
local Public = {}
|
||||
|
||||
-- local kraken_width = 31 --not old code, just commented for luacheck
|
||||
-- local kraken_height = 31 --not old code, just commented for luacheck
|
||||
|
||||
local kraken_bps = {
|
||||
[[0eNqd2tuOmzAQgOF38TWR8Nj4wKtUe5EmaIuUhSihh9Uq714IdtWLVpp/r1aRvh1mxgQYnA/z9fJ9uN7GaTH9h7lPx+thmQ+vt/G8ff5leuca8779eTRmPM3T3fRfVji+TsfLRpb362B6My7Dm2nMdHzbPv2c5/MwHU7fhvtitn+czsMayz5eGrOMl2EPcp3v4zLOUzmSfR7IhsefMOvhTrdhGdYQ/9HO6rTssSPSCelMtCDtWqSVPdkXVlqkE9LKKv2uEW6Rjkgri+xI2jt2BGeCbYs0iq1tSCA17tgTHAlGOWeCta0u2iKNMpGANOqfdtHjU3cEB4IjwVaQZrFRQwR1RLuQac/EIR2JFhRblN/fvGfCdCRaBGlllbYlJ2zREemEtLaFlbNctHfVypWXNmvJNaLogHRGWnsFr5xlrm66ZU0X1EVBd5/KA+OR8Yw4bIywUrUXjMod49rvqSOPQUVr73KVO8ZhMh3jgfHIeGI8I64+IR16BLAenQOerZJnq+TZKnm2Sp6tkmerxEbDylmpwkrVju4WzYdFe6QtC25h9I7xwHhkPDGeERe2psKSEZaM+gQr8yXSgrRjmbDgFkb3jHeMB8Yj44lx7QkT2RMhm6grd4x7xjvGA+ORce0yJTZzJLZMiTUysUYm1kj2xqFybSMza2RmubO3DtKSubNobeqVB8a1qaORWdi+jNjP5KLea7Fss4VN2CLkjUzRGWl1G9lMK2ymFYcKdahQNucVrh2vK1de7sSjQj0qlI1KhWuHQmHTiaAtI2F7RsIewgtXp452gorukGaZZKTVTWTPghI+00TtdCpoI0bQTkzRCemMtGWpqLvCnnYK1853lf+z1Jdm/wlF/9cPMhrzY7jdnwEkWR+zRO+Cz+sBH78BXJmyLg==]],
|
||||
[[0eNqdmt2O2jAQRt/F19lVPPFfeJVqVbFgbSNBQJBti1Z59ybEqaoWtXN6hSKdDJ/HY/sbw4d5Pbzn86XrB7P5MNd+e34aTk9vl24/P383m6apzG3+GCvT7U791Ww+TWD31m8PMzLcztlsTDfko6lMvz3OT99Op33un3Zf8nUw84v9Pk+x7PhSmdwP3dDlJc794fa5fz++5ssEPI5QmfPpOr106osoG579XVb97Mex+iOOKOPUJcwc71GcRhmnkX8EcnRgc8RxTtfQHUqufkeXLxx/Rp4mZ3fJQzbz9z+EhcANgZ0OFg57HbxUaSCwVYZ2JPQCW4doJMQyJRHRSUd7kpIFjgRGMphoQUJEGTsQ2QHNTECDDEh2JLIjKr+IBrnQ4hGNlAhTosxJIglMaLUnlO6FFkF0g2jlntaSlLQoJQstNaK1J2RNdBdaK7zgWuV2OVRbRKu1FFwbXZCWhbY1wz3DA8O12ostsAwXhjcMdwz3DA8MjwxPDNdOk0ML1bG0M/9mmYGzzMFZZuEs83ArztKuPWFWnOVdWN6F5V1Y3rWOwXrSqFjknS0yzxa550K3iFbv7J5tpp4tU8+WqWfL1LNl6tkyZV3LirNpEjZNwqZJvQn4/1lIwjIj2swEcvlQaI9otRcIrNoDq/bAqj2wamfdq2Xt64qzOVWXQEQlENkWFlkNRFYDkdVAZDXAenvLmvsVTwxnk6qugYRqIKEzMrEzMrECS6wE2HWDZfcNKx4ZnhjO8t5o894iU4UuNAqtTiO70ii4dqBSE69Z6Ihoy4JrjcaKC8LVebHkcC90QLRluLZPWnHHcOU6EvSTi7DbmIKrpQuT3iDp7P6j4GrpDZPukHR2oSHsDkFYH77i2pGiTllYTyisJxTWtRVcmBh1HlG3IawfEObYC67eeiOSHtFeykyvMBcrzMVKQtITOkyZtRNm7QT5HfmL33mplj96bH7520hlvubL9f6+JOtiK9E1wbVTGz/+ALfE6PI=]],
|
||||
[[0eNqdmctu4kAQRf+l10aiyv3kV0ZZMGBlLBEbgecRRfz7GOgezSZSnawipEP51u1HbuEP9/30czhfxmlxuw93nfbnzTJvXi/j8f75j9v1fefe739unRsP83R1u28rOL5O+9MdWd7Pg9u5cRneXOem/dv90+95Pg7T5vBjuC7u/sXpOKy15PbSuWU8Dc8i5/k6LuM8tSc9HiT+9q/M+rjDZViGtcRndEB0tNH+QXsCBwIjGUy0IiHKaidEZxsdiNmBmB2Qf5VOhNYe0ahJRV1a3Y7EwEh2a0QHMqK1icjtiNxODzoR2Npk+oIQ67LnB50JXAgsSIdVdSFCChJS0B4paGlkS3RX2iq84ioMVyMuTzFbhkeEK6tublWfYiCuDI8MTwwvCDcb2bNWWbYSFq6EpauGJ4Znhlt99+x4eLYjK94z3DM8MDwyPDE8I1yZM+b7+hmKekQXRJuPXmBbILAtENgWYJFYWCZueGY4812Z78p8V2akMiOVGanMSLUaGcnEJWhiEDQyVDohOiOaeWI+pZGdUjYbCRuOGs5sFOajMCPNOSayQBjZHRDZKU1sVdkw2HAoJjE8M9y6qpkdj8yMZBNnwyPDE8OtRhYWCAsLD4W1WtCq6hZl34YLwwPDrdrZWNvwwHAmRpkY66WnylpV1qp+RYz1Bm648eLQnvzTrrTZGDbVKptqK26dUBpuFeNJ9ql0QbS5UTYXKnsvoYFEwkpnRAsrbk0PiqKvouirLBEqS4QVt04nmshEUOmIaGHFhVWHjVrHMM1krlIWepSFHi3kBxBlqaThsLpneGC40Zi+xgxEK6KNtvSClMjnSl665+v33X8v8zv3a7hcH9/XLD4VTb6Pvqyb+fYX8FohZA==]],
|
||||
[[0eNqV2dtq4zAQgOF30bUD0ehk+1WWXqSJ6BpSO8TeQyl599qxtOzFLsx/VQJf5NF0LI2UT/N6/ZFv92FcTP9p5vF0OyzT4e0+XLbPv03vXGM+tj+PxgznaZxN/22Fw9t4um5k+bhl05thye+mMePpffv0a5oueTycv+d5MdsXx0tex7KPl8YswzXvg9ymeViGaaxPej7IxsefYdbHne95yesQ/9ESdNo/NcKR4ESwRZpNUVDYoowkPLUnGI3cEtwRbFEc2lxHEkhEgexaPNLKsNMeyRHpRLQ27hZF0qKVYdfikFbG3e2RWKQj0SJIK2dpj3sownhEXJRpsZYFY1kwhXeIi7IUrbDYhcUuLHbHgincMx4Yj4wnxpU7hfUsM4U7xj3jgfHIeGIcJrJDXP02ebZweLREWtQvFK3dkyq3jLPQ1QUZWEEGVpCBFSTrvCpvGWf/VWGJFO3okTTGRQekI9IJ6RZpdTFGVoyRFWNkxci678phZli5CEuksEQKm6qwqcI3wx0Z166miS2+iS2+iRVwYgWcWAGzY1jlLeMd4sIyo72TsOxUWLll3DMeGIdTTYy3jHeIC8uM9tLBdqgL61gNsCN25YnxlnE2VW2vLEeSR2En+MoT4tq+vXLl+isWzZRdD1SeENdu2ZUrXyURVO3CbhMqT4hr3+vKtcE4NlV23i9c2/uIRxXmWejshF24tg8TdL0u6H5d2FFM2GFJ0IFGWCcurD2VRA5uRQek1a8d69gK1zbWwhqNwtWjs/20cO3oju1hju1hhcNgtCcUx3alwv89+kuz/7za//VjbWN+5vv8HEBa61Mnybvou3UZeXwB67xzTA==]]
|
||||
}
|
||||
|
||||
Public.kraken_slots = 4
|
||||
local kraken_positions = {
|
||||
[1] = {first = {x = -40.5, y = -59.5}, second = {x = -15.5, y = -49.5}, third = {x = -32.5, y = -39.5}, final = {x = -24.5, y = -30.5},},
|
||||
[2] = {first = {x = 28.5, y = -59.5}, second = {x = 10.5, y = -49.5}, third = {x = 30.5, y = -39.5}, final = {x = 13.5, y = -30.5},},
|
||||
[3] = {first = {x = -40.5, y = 59.5}, second = {x = -15.5, y = 49.5}, third = {x = -32.5, y = 39.5}, final = {x = -24.5, y = 29.5},},
|
||||
[4] = {first = {x = 28.5, y = 59.5}, second = {x = 10.5, y = 49.5}, third = {x = 30.5, y = 39.5}, final = {x = 13.5, y = 29.5},},
|
||||
-- [1] = {first = {x = 96.5, y = 0.5}, second = {x = 81.5, y = 5.5}, third = {x = 66.5, y = -4.5}, final = {x = 51.5, y = 0.5},}
|
||||
}
|
||||
|
||||
local kraken_tick_token =
|
||||
Token.register(
|
||||
function(data)
|
||||
Public.kraken_tick(data.crew_id, data.kraken_id, data.step, data.substep)
|
||||
end
|
||||
)
|
||||
function Public.kraken_tick(crew_id, kraken_id, step, substep)
|
||||
Memory.set_working_id(crew_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if not (memory.id and memory.id > 0) then return end --check if crew disbanded
|
||||
if memory.game_lost then return end
|
||||
local surface = game.surfaces[memory.sea_name]
|
||||
local kraken_data = memory.active_sea_enemies.krakens[kraken_id]
|
||||
if not kraken_data then return end --check if kraken died
|
||||
local kraken_spawner_entity = kraken_data.spawner_entity
|
||||
|
||||
if step == 1 then
|
||||
if substep == 1 then
|
||||
Effects.kraken_effect_3(surface, kraken_data.position, 10)
|
||||
end
|
||||
if substep < 32 then
|
||||
Effects.kraken_effect_1(surface, kraken_data.position, substep/32 * 6.283)
|
||||
Task.set_timeout_in_ticks(1, kraken_tick_token, {crew_id = crew_id, kraken_id = kraken_id, step = 1, substep = substep + 1})
|
||||
else
|
||||
Task.set_timeout_in_ticks(1, kraken_tick_token, {crew_id = crew_id, kraken_id = kraken_id, step = 2, substep = 1})
|
||||
end
|
||||
elseif step == 2 then
|
||||
local p1 = kraken_positions[kraken_id].first
|
||||
local p2 = kraken_positions[kraken_id].second
|
||||
local p3 = kraken_positions[kraken_id].third
|
||||
local p4 = kraken_positions[kraken_id].final
|
||||
if substep <= 30 then
|
||||
if substep < 5 then
|
||||
Public.kraken_move(kraken_id, p1, substep % 4 + 1)
|
||||
elseif substep < 10 then
|
||||
Public.kraken_move(kraken_id, Utils.interpolate(p1, p2, (substep-5) / 5), substep % 4 + 1)
|
||||
elseif substep < 15 then
|
||||
Public.kraken_move(kraken_id, p2, substep % 4 + 1)
|
||||
elseif substep < 20 then
|
||||
Public.kraken_move(kraken_id, Utils.interpolate(p2, p3, (substep-15) / 5), substep % 4 + 1)
|
||||
elseif substep < 25 then
|
||||
Public.kraken_move(kraken_id, p3, substep % 4 + 1)
|
||||
elseif substep <= 30 then
|
||||
Public.kraken_move(kraken_id, Utils.interpolate(p3, p4, (substep-25) / 5), substep % 4 + 1)
|
||||
end
|
||||
Task.set_timeout_in_ticks(15, kraken_tick_token, {crew_id = crew_id, kraken_id = kraken_id, step = 2, substep = substep + 1})
|
||||
else
|
||||
Task.set_timeout_in_ticks(6, kraken_tick_token, {crew_id = crew_id, kraken_id = kraken_id, step = 3, substep = 1})
|
||||
end
|
||||
elseif step == 3 then
|
||||
Public.kraken_move(kraken_id, kraken_data.position, substep % 4 + 1)
|
||||
|
||||
-- regen:
|
||||
local healthbar = memory.healthbars and memory.healthbars[kraken_spawner_entity.unit_number]
|
||||
if healthbar then
|
||||
local new_health = Math.min(healthbar.health + Balance.kraken_regen_scale, kraken_data.max_health)
|
||||
healthbar.health = new_health
|
||||
Common.update_healthbar_rendering(healthbar, new_health)
|
||||
end
|
||||
|
||||
if substep % 4 == 0 then
|
||||
local crewmembers = Common.crew_get_crew_members()
|
||||
local p_can_fire_at = {}
|
||||
for _, player in pairs(crewmembers) do
|
||||
local p = player.position
|
||||
if player.surface == surface then
|
||||
-- if player.surface == surface and Public.on_boat(memory.boat, p) then
|
||||
p_can_fire_at[#p_can_fire_at + 1] = p
|
||||
end
|
||||
end
|
||||
|
||||
if #p_can_fire_at > 0 then
|
||||
local p_fire = p_can_fire_at[Math.random(#p_can_fire_at)]
|
||||
local stream = surface.create_entity{
|
||||
name = 'acid-stream-spitter-big',
|
||||
position = kraken_data.position,
|
||||
force = memory.enemy_force_name,
|
||||
source = kraken_data.position,
|
||||
target = p_fire,
|
||||
max_range = 500,
|
||||
speed = 0.1
|
||||
}
|
||||
memory.kraken_stream_registrations[#memory.kraken_stream_registrations + 1] = {number = script.register_on_entity_destroyed(stream), position = p_fire}
|
||||
Effects.kraken_effect_4(surface, kraken_data.position)
|
||||
end
|
||||
end
|
||||
|
||||
if substep % 50 > 40 then
|
||||
-- if substep % 70 == 69 then
|
||||
-- Public.kraken_spawn_biters(kraken_id)
|
||||
-- end
|
||||
Task.set_timeout_in_ticks(5, kraken_tick_token, {crew_id = crew_id, kraken_id = kraken_id, step = 3, substep = substep + 1})
|
||||
elseif substep % 50 > 30 then
|
||||
Task.set_timeout_in_ticks(10, kraken_tick_token, {crew_id = crew_id, kraken_id = kraken_id, step = 3, substep = substep + 1})
|
||||
else
|
||||
Task.set_timeout_in_ticks(30, kraken_tick_token, {crew_id = crew_id, kraken_id = kraken_id, step = 3, substep = substep + 1})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_entity_destroyed(event)
|
||||
local registration_number = event.registration_number
|
||||
|
||||
local p
|
||||
local memory
|
||||
for i = 1,3 do
|
||||
Memory.set_working_id(i)
|
||||
memory = Memory.get_crew_memory()
|
||||
if memory.kraken_stream_registrations then
|
||||
for j, r in pairs(memory.kraken_stream_registrations) do
|
||||
if r.number == registration_number then
|
||||
p = r.position
|
||||
memory.kraken_stream_registrations = Utils.ordered_table_with_index_removed(memory.kraken_stream_registrations, j)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if p then break end
|
||||
end
|
||||
if p then
|
||||
local surface = game.surfaces[memory.sea_name]
|
||||
if not surface and surface.valid then return end
|
||||
|
||||
local spits_here = surface.find_entities_filtered{position = p, radius = 0.5, name = 'acid-splash-fire-spitter-big'}
|
||||
if spits_here and #spits_here > 0 then
|
||||
for _, s in pairs(spits_here) do
|
||||
if s.valid then s.destroy() end
|
||||
end
|
||||
end
|
||||
|
||||
local p2 = surface.find_non_colliding_position('medium-biter', p, 10, 0.2)
|
||||
if not p2 then return end
|
||||
local name = Common.get_random_unit_type(memory.evolution_factor + Balance.kraken_spawns_base_extra_evo)
|
||||
surface.create_entity{name = name, position = p2, force = memory.enemy_force_name}
|
||||
Effects.kraken_effect_2(surface, p2)
|
||||
|
||||
local evo_increase = Balance.kraken_evo_increase_per_shot()
|
||||
|
||||
if not memory.kraken_evo then memory.kraken_evo = 0 end
|
||||
memory.kraken_evo = memory.kraken_evo + evo_increase
|
||||
Common.increment_evo(evo_increase)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.try_spawn_kraken()
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[memory.sea_name]
|
||||
if not (surface and surface.valid) then return end -- check sea still exists
|
||||
|
||||
if not memory.active_sea_enemies then memory.active_sea_enemies = {} end
|
||||
if not memory.active_sea_enemies.krakens then memory.active_sea_enemies.krakens = {} end
|
||||
|
||||
local possible_slots = {}
|
||||
for i = 1, Public.kraken_slots do
|
||||
if not memory.active_sea_enemies.krakens[i] then
|
||||
possible_slots[#possible_slots + 1] = i
|
||||
end
|
||||
end
|
||||
|
||||
if #possible_slots > 0 then
|
||||
local kraken_id = possible_slots[Math.random(#possible_slots)]
|
||||
-- if _DEBUG then game.print('spawning kraken in slot ' .. kraken_id) end
|
||||
local p = kraken_positions[kraken_id].first
|
||||
memory.active_sea_enemies.krakens[kraken_id] = {
|
||||
state = 'submerged',
|
||||
position = p,
|
||||
max_health = Balance.kraken_health(),
|
||||
spawner_entity = nil,
|
||||
frame = nil,
|
||||
}
|
||||
|
||||
Task.set_timeout_in_ticks(10, kraken_tick_token, {crew_id = memory.id, kraken_id = kraken_id, step = 1, substep = 1})
|
||||
end
|
||||
end
|
||||
|
||||
function Public.kraken_move(kraken_id, new_p, new_frame)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[memory.sea_name]
|
||||
if not surface and surface.valid then return end -- check sea still exists
|
||||
local kraken_data = memory.active_sea_enemies.krakens[kraken_id]
|
||||
|
||||
local kraken_tile = CoreData.kraken_tile
|
||||
|
||||
local old_p = kraken_data.position
|
||||
local old_frame = kraken_data.frame
|
||||
|
||||
local new_p_2 = {x = Math.ceil(new_p.x), y = Math.ceil(new_p.y)}
|
||||
local old_p_2 = {x = Math.ceil(old_p.x), y = Math.ceil(old_p.y)}
|
||||
|
||||
local new_tile_positions = Common.tile_positions_from_blueprint_arrayform(kraken_bps[new_frame], Utils.psum{new_p_2, {x = -16, y = -16}})
|
||||
local old_tile_positions = {}
|
||||
if old_frame then
|
||||
old_tile_positions = Common.tile_positions_from_blueprint_arrayform(kraken_bps[old_frame], Utils.psum{old_p_2, {x = -16, y = -16}})
|
||||
end
|
||||
|
||||
local new_tile_positions2 = Utils.exclude_position_arrays(new_tile_positions, old_tile_positions)
|
||||
|
||||
local tiles1 = {}
|
||||
for x, xtab in pairs(new_tile_positions2) do
|
||||
for y, _ in pairs(xtab) do
|
||||
tiles1[#tiles1 + 1] = {name = kraken_tile, position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles1)
|
||||
|
||||
if kraken_data.spawner_entity and kraken_data.spawner_entity.valid then
|
||||
kraken_data.spawner_entity.teleport(new_p_2.x - old_p_2.x, new_p_2.y - old_p_2.y)
|
||||
else
|
||||
kraken_data.spawner_entity = surface.create_entity{name = 'biter-spawner', position = new_p_2, force = memory.enemy_force_name}
|
||||
Common.new_healthbar(true, kraken_data.spawner_entity, kraken_data.max_health, kraken_id)
|
||||
end
|
||||
|
||||
if old_frame then --cleanup old tiles
|
||||
local old_tile_positions2 = Utils.exclude_position_arrays(old_tile_positions, new_tile_positions)
|
||||
local tiles2 = {}
|
||||
for x, xtab in pairs(old_tile_positions2) do
|
||||
for y, _ in pairs(xtab) do
|
||||
tiles2[#tiles2 + 1] = {name = 'deepwater', position = {x = x, y = y}}
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles2, true, false)
|
||||
end
|
||||
|
||||
kraken_data.position = new_p
|
||||
kraken_data.frame = new_frame
|
||||
end
|
||||
|
||||
function Public.kraken_die(kraken_id)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface = game.surfaces[memory.sea_name]
|
||||
if not surface and surface.valid then return end -- check sea still exists
|
||||
local kraken_data = memory.active_sea_enemies.krakens[kraken_id]
|
||||
|
||||
if kraken_data.spawner_entity and kraken_data.spawner_entity.valid then
|
||||
kraken_data.spawner_entity.destroy()
|
||||
end
|
||||
Effects.kraken_effect_5(surface, kraken_data.position)
|
||||
|
||||
local tiles2 = {}
|
||||
for x = -16, 16 do
|
||||
for y = -16, 16 do
|
||||
tiles2[#tiles2 + 1] = {name = 'deepwater', position = Utils.psum{kraken_data.position, {x = x, y = y}}}
|
||||
end
|
||||
end
|
||||
surface.set_tiles(tiles2, true, false)
|
||||
|
||||
memory.active_sea_enemies.krakens[kraken_id] = nil
|
||||
|
||||
local reward = Balance.kraken_kill_reward()
|
||||
Common.give_items_to_crew(reward)
|
||||
|
||||
local force = memory.force
|
||||
if not (force and force.valid) then return end
|
||||
Common.notify_force_light(force,'Granted ' .. reward[1].count .. ' [item=sulfuric-acid-barrel]')
|
||||
end
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.add(defines.events.on_entity_destroyed, on_entity_destroyed)
|
||||
|
||||
return Public
|
||||
|
60
maps/pirates/surfaces/sea/sea.lua
Normal file
60
maps/pirates/surfaces/sea/sea.lua
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- 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 Token = require 'utils.token'
|
||||
-- local Task = require 'utils.task'
|
||||
-- local Kraken = require 'maps.pirates.surfaces.sea.kraken'
|
||||
local SurfacesCommon = require 'maps.pirates.surfaces.common'
|
||||
|
||||
local Public = {}
|
||||
local enum = {
|
||||
DEFAULT = 'Default',
|
||||
}
|
||||
Public.enum = enum
|
||||
|
||||
Public.Data = {}
|
||||
Public.Data.width = 384
|
||||
Public.Data.height = 384
|
||||
|
||||
function Public.ensure_sea_surface()
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local seaname = SurfacesCommon.encode_surface_name(memory.id, 0, SurfacesCommon.enum.SEA, enum.DEFAULT)
|
||||
|
||||
if not game.surfaces[seaname] then
|
||||
local width = Public.Data.width
|
||||
local height = Public.Data.height
|
||||
local map_gen_settings = Common.default_map_gen_settings(width, height)
|
||||
|
||||
map_gen_settings.autoplace_settings.decorative.treat_missing_as_default = false
|
||||
|
||||
local surface = game.create_surface(seaname, map_gen_settings)
|
||||
surface.freeze_daytime = true
|
||||
surface.daytime = 0
|
||||
surface.show_clouds = false
|
||||
|
||||
memory.sea_name = seaname
|
||||
end
|
||||
end
|
||||
|
||||
function Public.terrain(args)
|
||||
args.tiles[#args.tiles + 1] = {name = 'deepwater', position = args.p}
|
||||
local fishrng = Math.random(110)
|
||||
if fishrng == 1 then
|
||||
args.entities[#args.entities + 1] = {name = 'fish', position = args.p}
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function Public.chunk_structures()
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
return Public
|
||||
|
872
maps/pirates/surfaces/surfaces.lua
Normal file
872
maps/pirates/surfaces/surfaces.lua
Normal file
@ -0,0 +1,872 @@
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Math = require 'maps.pirates.math'
|
||||
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 Boats = require 'maps.pirates.structures.boats.boats'
|
||||
-- local Lobby = require 'maps.pirates.surfaces.lobby'
|
||||
-- local Dock = require 'maps.pirates.surfaces.dock'
|
||||
local Hold = require 'maps.pirates.surfaces.hold'
|
||||
local Cabin = require 'maps.pirates.surfaces.cabin'
|
||||
-- local Sea = require 'maps.pirates.surfaces.sea.sea'
|
||||
local Islands = require 'maps.pirates.surfaces.islands.islands'
|
||||
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
|
||||
local Quest = require 'maps.pirates.quest'
|
||||
local Parrot = require 'maps.pirates.parrot'
|
||||
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 Server = require 'utils.server'
|
||||
|
||||
local Public = {}
|
||||
local enum = SurfacesCommon.enum
|
||||
Public.enum = enum
|
||||
|
||||
Public[enum.SEA] = require 'maps.pirates.surfaces.sea.sea'
|
||||
Public[enum.ISLAND] = require 'maps.pirates.surfaces.islands.islands'
|
||||
Public[enum.DOCK] = require 'maps.pirates.surfaces.dock'
|
||||
Public[enum.CROWSNEST] = require 'maps.pirates.surfaces.crowsnest'
|
||||
Public[enum.LOBBY] = require 'maps.pirates.surfaces.lobby'
|
||||
Public[enum.HOLD] = require 'maps.pirates.surfaces.hold'
|
||||
Public[enum.CABIN] = require 'maps.pirates.surfaces.cabin'
|
||||
Public[enum.CHANNEL] = require 'maps.pirates.surfaces.channel.channel'
|
||||
Public['SurfacesCommon'] = require 'maps.pirates.surfaces.common'
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.initialise_destination(o)
|
||||
o = o or {}
|
||||
|
||||
local memory = Memory.get_crew_memory()
|
||||
assert(memory.destinations, o.overworld_position)
|
||||
|
||||
local scope = Public.get_scope(o)
|
||||
|
||||
o.destination_index = #memory.destinations + 1 --assuming none are deleted
|
||||
memory.destinations[o.destination_index] = o
|
||||
|
||||
o.dynamic_data = o.dynamic_data or {}
|
||||
o.static_params = o.static_params or Utils.deepcopy(Public.get_scope(o).Data.static_params_default)
|
||||
|
||||
o.seed = o.seed or Math.random(1, 10000000)
|
||||
o.iconized_map = o.iconized_map or {}
|
||||
o.boat_extra_distance_from_shore = o.boat_extra_distance_from_shore or 0
|
||||
o.surface_name = o.surface_name or SurfacesCommon.encode_surface_name(memory.id, o.destination_index, o.type, o.subtype)
|
||||
|
||||
o.dynamic_data.other_map_generation_data = o.dynamic_data.other_map_generation_data or {}
|
||||
|
||||
if o.type == enum.ISLAND then
|
||||
|
||||
o.init_boat_state = Boats.enum_state.APPROACHING
|
||||
|
||||
Public.generate_detailed_island_data(o)
|
||||
|
||||
elseif o.type == enum.DOCK then
|
||||
|
||||
o.init_boat_state = Boats.enum_state.APPROACHING
|
||||
|
||||
o.iconized_map_width = scope.Data.iconized_map_width
|
||||
o.iconized_map_height = scope.Data.iconized_map_height
|
||||
end
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
|
||||
function Public.get_scope(destination)
|
||||
if destination.type then
|
||||
if destination.subtype then
|
||||
return Public[destination.type][destination.subtype]
|
||||
else
|
||||
return Public[destination.type]
|
||||
end
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.on_surface_generation(destination)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
-- game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = Balance.defaultai_attack_pollution_consumption_modifier()
|
||||
-- Event_functions.flamer_nerfs()
|
||||
|
||||
if destination.type == enum.ISLAND then
|
||||
local subtype = destination.subtype
|
||||
|
||||
destination.dynamic_data.rocketsilomaxhp = Balance.silo_max_hp
|
||||
destination.dynamic_data.rocketsilohp = Balance.silo_max_hp
|
||||
destination.dynamic_data.rocketsilochargedbools = {}
|
||||
destination.dynamic_data.rocketsiloenergyconsumed = 0
|
||||
destination.dynamic_data.rocketsiloenergyconsumedwithinlasthalfsecond = 0
|
||||
destination.dynamic_data.energychargedinsilosincelastcheck = 0
|
||||
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
|
||||
destination.dynamic_data.hidden_ore_remaining_abstract = Utils.deepcopy(destination.static_params.abstract_ore_amounts)
|
||||
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
|
||||
destination.dynamic_data.ore_types_spawned = {}
|
||||
|
||||
destination.dynamic_data.buried_treasure = {}
|
||||
|
||||
-- elseif destination.type == enum.DOCK then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.destination_on_collide(destination)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local name = destination.static_params.name and destination.static_params.name or 'NameNotFound'
|
||||
local message = '[' .. memory.name .. '] Loading destination ' .. (memory.destinationsvisited_indices and (#memory.destinationsvisited_indices + 1) or 0) .. ', ' .. name .. '.'
|
||||
Common.notify_game(message)
|
||||
|
||||
if destination.type ~= Public.enum.DOCK then
|
||||
local index = destination.destination_index
|
||||
Crowsnest.paint_around_destination(index, CoreData.overworld_loading_tile)
|
||||
end
|
||||
|
||||
if destination and destination.static_params and destination.static_params.base_cost_to_undock then
|
||||
local replace = {}
|
||||
for item, count in pairs(destination.static_params.base_cost_to_undock) do
|
||||
if item == 'uranium-235' or item == 'launch_rocket' then
|
||||
replace[item] = count
|
||||
else
|
||||
replace[item] = Math.ceil(count * Balance.cost_to_leave_multiplier())
|
||||
end
|
||||
end
|
||||
destination.static_params.base_cost_to_undock = replace
|
||||
end
|
||||
|
||||
if destination.type == Public.enum.ISLAND then
|
||||
local index = destination.destination_index
|
||||
Crowsnest.paint_around_destination(index, CoreData.overworld_loading_tile)
|
||||
|
||||
|
||||
|
||||
if destination.subtype == Islands.enum.RADIOACTIVE then
|
||||
Parrot.parrot_radioactive_tip_1()
|
||||
else
|
||||
|
||||
local scheduled_raft_raids
|
||||
-- temporarily placed this back here, as moving it to shorehit broke things:
|
||||
local playercount = Common.activecrewcount()
|
||||
local max_evo
|
||||
|
||||
local difficulty_name = CoreData.get_difficulty_name_from_value(Common.difficulty())
|
||||
if difficulty_name == CoreData.difficulty_options[1].text then
|
||||
if memory.overworldx/40 < 20 then
|
||||
max_evo = 0.9 - (20 - memory.overworldx/40) * 1/100
|
||||
else
|
||||
max_evo = 0.91 + (memory.overworldx/40 - 20) * 0.25/100
|
||||
end
|
||||
elseif difficulty_name == CoreData.difficulty_options[2].text then
|
||||
if memory.overworldx/40 < 15 then
|
||||
max_evo = 0.9 - (15 - memory.overworldx/40) * 0.5/100
|
||||
else
|
||||
max_evo = 0.91 + (memory.overworldx/40 - 15) * 0.25/100
|
||||
end
|
||||
else
|
||||
if memory.overworldx/40 < 12 then
|
||||
max_evo = 0.9
|
||||
else
|
||||
max_evo = 0.91 + (memory.overworldx/40 - 12) * 0.25/100
|
||||
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
|
||||
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 or _DEBUG 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
|
||||
end
|
||||
|
||||
destination.static_params.scheduled_raft_raids = scheduled_raft_raids
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if memory.overworldx == 40*5 then
|
||||
Parrot.parrot_boats_warning()
|
||||
elseif memory.overworldx == 800 then
|
||||
Parrot.parrot_800_tip()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.destination_on_arrival(destination)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
-- game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = Balance.defaultai_attack_pollution_consumption_modifier()
|
||||
-- Event_functions.flamer_nerfs()
|
||||
|
||||
memory.floating_pollution = 0
|
||||
|
||||
-- catching a fallthrough error I've observed
|
||||
if not memory.active_sea_enemies then memory.active_sea_enemies = {} end
|
||||
memory.active_sea_enemies.krakens = {}
|
||||
|
||||
if destination.type == enum.ISLAND then
|
||||
|
||||
destination.dynamic_data.rocketsiloenergyneeded = Balance.silo_energy_needed_MJ() * 1000000
|
||||
destination.dynamic_data.rocketcoalreward = Balance.launch_fuel_reward()
|
||||
|
||||
if destination.subtype == Islands.enum.RADIOACTIVE then
|
||||
destination.dynamic_data.time_remaining = -1
|
||||
elseif destination.subtype == Islands.enum.MAZE then --more time
|
||||
destination.dynamic_data.time_remaining = Math.ceil(1.08 * 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 then
|
||||
Quest.initialise_random_quest()
|
||||
-- else
|
||||
-- if _DEBUG then
|
||||
-- Quest.initialise_random_quest()
|
||||
-- end
|
||||
end
|
||||
|
||||
memory.enemy_force.reset_evolution()
|
||||
local base_evo = Balance.base_evolution_leagues(memory.overworldx)
|
||||
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
|
||||
destination.dynamic_data.evolution_accrued_sandwurms = 0
|
||||
else
|
||||
destination.dynamic_data.evolution_accrued_nests = 0
|
||||
end
|
||||
if destination.subtype ~= Islands.enum.RADIOACTIVE then
|
||||
destination.dynamic_data.evolution_accrued_silo = 0
|
||||
end
|
||||
|
||||
memory.scripted_biters = {}
|
||||
memory.scripted_unit_groups = {}
|
||||
memory.floating_pollution = 0
|
||||
|
||||
if destination.subtype == Islands.enum.RADIOACTIVE then
|
||||
Islands[Islands.enum.RADIOACTIVE].spawn_structures()
|
||||
end
|
||||
-- -- invulnerable bases on islands 21-25
|
||||
-- if memory.overworldx >= 21 and memory.overworldx < 25 then
|
||||
-- local surface = game.surfaces[destination.surface_name]
|
||||
-- if not (surface and surface.valid) then return end
|
||||
-- local spawners = surface.find_entities_filtered({type = 'unit-spawner', force = memory.enemy_force_name})
|
||||
-- for _, s in pairs(spawners) do
|
||||
-- s.destructible = false
|
||||
-- end
|
||||
-- end
|
||||
|
||||
elseif destination.type == enum.DOCK then
|
||||
|
||||
-- -- kick players out of crow's nest
|
||||
-- local crowsnestname = SurfacesCommon.encode_surface_name(memory.id, 0, enum.CROWSNEST, nil)
|
||||
-- for _, player in pairs(game.connected_players) do
|
||||
-- if player.surface.name == crowsnestname then
|
||||
-- Public.player_exit_crows_nest(player, {x = 5, y = 0})
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- New dock class sales:
|
||||
local class_for_sale = Classes.generate_class_for_sale()
|
||||
destination.static_params.class_for_sale = class_for_sale
|
||||
|
||||
end
|
||||
|
||||
local name = destination.static_params.name and destination.static_params.name or 'NameNotFound'
|
||||
local message = '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.')
|
||||
end
|
||||
if destination.static_params.name == 'Dock' then
|
||||
message = message .. ' ' .. 'New trades are available in the Captain\'s Store.'
|
||||
end
|
||||
Common.notify_force(memory.force, message)
|
||||
|
||||
if destination.type == enum.ISLAND then
|
||||
|
||||
local points_to_avoid = {}
|
||||
|
||||
if destination.subtype ~= Islands.enum.RADIOACTIVE then
|
||||
local silo_position = Islands.spawn_silo_setup()
|
||||
if silo_position then
|
||||
points_to_avoid[#points_to_avoid + 1] = {x = silo_position.x, y = silo_position.y, r = 22}
|
||||
end
|
||||
end
|
||||
|
||||
Islands.spawn_ores_on_arrival(destination, points_to_avoid)
|
||||
|
||||
if memory.overworldx >= Balance.covered_first_appears_at and destination.subtype ~= Islands.enum.RADIOACTIVE then
|
||||
local class_for_sale = Classes.generate_class_for_sale()
|
||||
destination.static_params.class_for_sale = class_for_sale
|
||||
|
||||
local covered = Islands.spawn_covered(destination, points_to_avoid)
|
||||
points_to_avoid[#points_to_avoid + 1] = {x = covered.x, y = covered.y, r = 25}
|
||||
end
|
||||
|
||||
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
|
||||
local force = memory.force
|
||||
force.manual_mining_speed_modifier = 0.8
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.destination_on_departure(destination)
|
||||
local memory = Memory.get_crew_memory()
|
||||
-- local boat = memory.boat
|
||||
|
||||
if memory.overworldx == 40*9 then
|
||||
Parrot.parrot_kraken_warning()
|
||||
end
|
||||
|
||||
if destination.subtype and destination.subtype == Islands.enum.MAZE then
|
||||
local force = memory.force
|
||||
force.manual_mining_speed_modifier = 3 --put back to normal
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.destination_on_crewboat_hits_shore(destination)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local boat = memory.boat
|
||||
|
||||
destination.dynamic_data.timeratlandingtime = Common.current_destination().dynamic_data.timer
|
||||
|
||||
Boats.place_landingtrack(boat, CoreData.landing_tile)
|
||||
|
||||
Boats.place_boat(boat, CoreData.static_boat_floor, false, false)
|
||||
|
||||
if destination.type == enum.ISLAND then
|
||||
|
||||
if memory.overworldx == 0 then
|
||||
Parrot.parrot_0()
|
||||
-- elseif memory.overworldx == 80 then
|
||||
-- Parrot.parrot_80()
|
||||
end
|
||||
|
||||
if destination.subtype == Islands.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'})
|
||||
for _, m in pairs(miners) do
|
||||
local direction = m.direction
|
||||
local position = m.position
|
||||
m.destroy()
|
||||
surface.create_entity{name = 'electric-mining-drill', direction = direction, position = position}
|
||||
end
|
||||
|
||||
Parrot.parrot_radioactive_tip_2()
|
||||
elseif destination.subtype == Islands.enum.MAZE and memory.overworldx == Common.maze_minimap_jam_league then
|
||||
Parrot.parrot_maze_tip_1()
|
||||
end
|
||||
|
||||
if memory.merchant_ships_unlocked or _DEBUG then
|
||||
Islands.spawn_merchant_ship(destination)
|
||||
|
||||
ShopMerchants.generate_merchant_trades(destination.dynamic_data.merchant_market)
|
||||
end
|
||||
end
|
||||
|
||||
if destination and destination.surface_name and game.surfaces[destination.surface_name] and game.surfaces[destination.surface_name].valid and (not (destination.dynamic_data and destination.dynamic_data.initial_spawner_count)) then
|
||||
--Note: This gives the wrong answer on the first island. Because the terrain hasn't finished generating yet.
|
||||
destination.dynamic_data.initial_spawner_count = Common.spawner_count(game.surfaces[destination.surface_name])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.generate_detailed_island_data(destination)
|
||||
|
||||
local scope = Public.get_scope(destination)
|
||||
|
||||
local frame_width = scope.Data.terraingen_frame_width
|
||||
local frame_height = scope.Data.terraingen_frame_height
|
||||
local boat_extra_distance_from_shore = destination.boat_extra_distance_from_shore
|
||||
|
||||
-- scale 1:32
|
||||
local chunks_horizontal = 2 * Math.floor(frame_width/64)
|
||||
local chunks_vertical = 2 * Math.floor(frame_height/64)
|
||||
|
||||
local entities = {}
|
||||
local entitymap = {}
|
||||
local tiles = {}
|
||||
local tiles2 = {}
|
||||
local leftboundary, rightboundary, topboundary, bottomboundary = chunks_horizontal/2 + 1, -chunks_horizontal/2 - 1, chunks_vertical/2 + 1, -chunks_vertical/2 - 1 -- reversed, because we'll iterate
|
||||
|
||||
-- local subtype = destination.subtype
|
||||
|
||||
local terrain_fn = scope.terrain
|
||||
|
||||
local noise_generator = Utils.noise_generator(scope.Data.noiseparams, destination.seed)
|
||||
|
||||
for y = -chunks_vertical/2, chunks_vertical/2 - 1, 1 do
|
||||
for x = -chunks_horizontal/2, chunks_horizontal/2 - 1, 1 do
|
||||
local macroposition = {x = x + 0.5, y = y + 0.5}
|
||||
local chunk_frameposition_topleft = {x = x * 32, y = y * 32}
|
||||
|
||||
-- average over the chunk
|
||||
local modalcounts = {}
|
||||
for y2 = 5, 27, 11 do
|
||||
for x2 = 5, 27, 11 do
|
||||
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}
|
||||
local tile = tiles3[1]
|
||||
if modalcounts[tile.name] then
|
||||
modalcounts[tile.name] = modalcounts[tile.name] + 1
|
||||
else
|
||||
modalcounts[tile.name] = 1
|
||||
end
|
||||
|
||||
if y2 == 16 and x2 == 16 and #entities3 > 0 and entities3[1] and entities3[1].visible_on_overworld then
|
||||
entitymap[macroposition] = entities3[1].name
|
||||
end
|
||||
end
|
||||
end
|
||||
local modaltile, max = 'hazard-concrete-left', 0
|
||||
for k, v in pairs(modalcounts) do
|
||||
if v > max then
|
||||
modaltile, max = k, v
|
||||
end
|
||||
end
|
||||
tiles[#tiles + 1] = {name = modaltile, position = macroposition}
|
||||
|
||||
if (not Utils.contains(CoreData.water_tile_names, modaltile)) then
|
||||
leftboundary, rightboundary, topboundary, bottomboundary = Math.min(leftboundary, x), Math.max(rightboundary, x + 1), Math.min(topboundary, y), Math.max(bottomboundary, y + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
leftboundary, rightboundary, topboundary, bottomboundary = leftboundary - 1, rightboundary + 1, topboundary - 1, bottomboundary + 1 --push out by one step to get some water
|
||||
|
||||
-- construct image, and record where entities can be placed:
|
||||
local positions_free_to_hold_resources = {}
|
||||
for _, tile in pairs(tiles) do
|
||||
local x = tile.position.x
|
||||
local y = tile.position.y
|
||||
if tile.name ~= 'water' and x >= leftboundary and x <= rightboundary and y >= topboundary and y <= bottomboundary then --nil represents water
|
||||
--arrange image so that {0,0} is on the centre of the left edge:
|
||||
local p = {x = x - leftboundary, y = y - (topboundary + bottomboundary)/2}
|
||||
if (topboundary + bottomboundary)/2 % 1 ~= 0 then
|
||||
p.y = p.y + 0.5 --adjust so that tiles land on half-integer positions
|
||||
end
|
||||
|
||||
tiles2[#tiles2 + 1] = {name = tile.name, position = p}
|
||||
|
||||
if (not Utils.contains(CoreData.tiles_that_conflict_with_resource_layer, tile.name)) then
|
||||
|
||||
local ename = entitymap[tile.position]
|
||||
if ename then
|
||||
entities[#entities + 1] = {name = ename, position = p}
|
||||
else
|
||||
if (p.x + 2) % 4 <= 2 and (p.y) % 4 <= 2 then --for the ingame minimap, the ore texture checker only colors these squares
|
||||
local nearby_es = {
|
||||
entitymap[{x = tile.position.x + 1, y = tile.position.y}],
|
||||
entitymap[{x = tile.position.x - 1, y = tile.position.y}],
|
||||
entitymap[{x = tile.position.x, y = tile.position.y + 1}],
|
||||
entitymap[{x = tile.position.x, y = tile.position.y - 1}],
|
||||
}
|
||||
if not (nearby_es[1] or nearby_es[2] or nearby_es[3] or nearby_es[4]) then
|
||||
positions_free_to_hold_resources[#positions_free_to_hold_resources + 1] = p
|
||||
-- if destination.destination_index == 3 then
|
||||
-- game.print(p)
|
||||
-- end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #positions_free_to_hold_resources > 0 then
|
||||
local orestoadd = {}
|
||||
for k, v in pairs(destination.static_params.abstract_ore_amounts) do
|
||||
if k == 'crude-oil' then
|
||||
local count = Math.ceil((v/20)^(1/2)) --assuming the abstract values are about 20 times as big as for other ores
|
||||
orestoadd[k] = {count = count, sizing_each = Common.oil_abstract_to_real(v)/count}
|
||||
else
|
||||
local count = Math.ceil(v^(1/2))
|
||||
orestoadd[k] = {count = count, sizing_each = Common.ore_abstract_to_real(v)/count}
|
||||
end
|
||||
end
|
||||
for k, v in pairs(orestoadd) do
|
||||
for i = 1, v.count do
|
||||
if #positions_free_to_hold_resources > 0 then
|
||||
local random_index = Math.random(#positions_free_to_hold_resources)
|
||||
local p = positions_free_to_hold_resources[random_index]
|
||||
|
||||
entities[#entities + 1] = {name = k, position = p, amount = v.sizing_each}
|
||||
|
||||
for j = random_index, #positions_free_to_hold_resources - 1 do
|
||||
positions_free_to_hold_resources[j] = positions_free_to_hold_resources[j+1]
|
||||
end
|
||||
positions_free_to_hold_resources[#positions_free_to_hold_resources] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- get more precise understanding of left-hand shore
|
||||
local xcorrection = 0
|
||||
for ystep = -10, 10, 10 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}
|
||||
local tile = tiles3[1]
|
||||
if (not Utils.contains(CoreData.water_tile_names, tile.name)) then
|
||||
xcorrection = Math.max(xcorrection, xstep + Math.abs(ystep))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- if xcorrection == 0 then xcorrection = 300 end
|
||||
|
||||
local iconwidth, iconheight = rightboundary - leftboundary, bottomboundary - topboundary
|
||||
iconwidth = iconwidth > 0 and iconwidth or 0 --make them 0 if negative
|
||||
iconheight = iconheight > 0 and iconheight or 0
|
||||
|
||||
local extension_to_left = Math.ceil(Common.boat_default_starting_distance_from_shore + boat_extra_distance_from_shore + Common.mapedge_distance_from_boat_starting_position - xcorrection)
|
||||
|
||||
local terraingen_coordinates_offset = {x = (leftboundary*32 + rightboundary*32)/2 - extension_to_left/2, y = (topboundary*32 + bottomboundary*32)/2}
|
||||
local width = rightboundary*32 - leftboundary*32 + extension_to_left
|
||||
local height = bottomboundary*32 - topboundary*32
|
||||
|
||||
local deepwater_terraingenframe_xposition = leftboundary*32 - Common.deepwater_distance_from_leftmost_shore
|
||||
local islandcenter_position = {x = extension_to_left/2, y = 0}
|
||||
local deepwater_xposition = deepwater_terraingenframe_xposition - terraingen_coordinates_offset.x
|
||||
|
||||
-- -- must ceil this, because if it's a half integer big things will teleport badly:
|
||||
-- local boat_starting_xposition = Math.ceil(- width/2 + Common.mapedge_distance_from_boat_starting_position)
|
||||
-- worse, must make this even due to rails:
|
||||
local boat_starting_xposition = 2*Math.ceil(
|
||||
(- width/2 + Common.mapedge_distance_from_boat_starting_position)/2
|
||||
)
|
||||
|
||||
destination.static_params.terraingen_coordinates_offset = terraingen_coordinates_offset
|
||||
destination.static_params.width = width
|
||||
destination.static_params.height = height
|
||||
|
||||
destination.static_params.islandcenter_position = islandcenter_position
|
||||
destination.static_params.deepwater_xposition = deepwater_xposition
|
||||
destination.static_params.deepwater_terraingenframe_xposition = deepwater_terraingenframe_xposition
|
||||
destination.static_params.boat_starting_xposition = boat_starting_xposition
|
||||
|
||||
destination.iconized_map.tiles = tiles2
|
||||
destination.iconized_map.entities = entities
|
||||
|
||||
destination.iconized_map_width = iconwidth
|
||||
destination.iconized_map_height = iconheight
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.create_surface(destination)
|
||||
|
||||
local surface_name = destination.surface_name
|
||||
if game.surfaces[surface_name] then return end
|
||||
|
||||
-- maybe can set width and height to be 0 here? if so, will need to change references to map_gen_settings.width elsewhere in code
|
||||
-- local mgs = Utils.deepcopy(Common.default_map_gen_settings(
|
||||
-- self.static_params.width or 512,
|
||||
-- self.static_params.height or 512,
|
||||
-- self.seed or Math.random(1, 1000000)
|
||||
-- ))
|
||||
|
||||
local mgs = Utils.deepcopy(Common.default_map_gen_settings(
|
||||
Math.max(0,destination.static_params.width) or 128,
|
||||
Math.max(0,destination.static_params.height) or 128,
|
||||
destination.seed or Math.random(1, 1000000)
|
||||
))
|
||||
|
||||
--todo: put into static_params
|
||||
|
||||
mgs.autoplace_settings.decorative.treat_missing_as_default = destination.static_params.default_decoratives
|
||||
|
||||
local surface = game.create_surface(surface_name, mgs)
|
||||
|
||||
surface.solar_power_multiplier = destination.static_params.solar_power_multiplier or 1
|
||||
surface.show_clouds = destination.static_params.clouds or false
|
||||
surface.min_brightness = destination.static_params.min_brightness or 0.15
|
||||
surface.brightness_visual_weights = destination.static_params.brightness_visual_weights or {1, 1, 1}
|
||||
surface.daytime = destination.static_params.starting_time_of_day or 0
|
||||
|
||||
local daynightcycletype = destination.static_params.daynightcycletype or 1
|
||||
|
||||
local ticksperday = CoreData.daynightcycle_types[daynightcycletype].ticksperday or 0
|
||||
|
||||
if ticksperday == 0 then
|
||||
surface.freeze_daytime = true
|
||||
ticksperday = ticksperday + 1 -- avoid divide by zero
|
||||
else
|
||||
surface.freeze_daytime = false
|
||||
end
|
||||
surface.ticks_per_day = ticksperday
|
||||
|
||||
Public.on_surface_generation(destination)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.clean_up(destination)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local oldsurface = game.surfaces[destination.surface_name]
|
||||
|
||||
if not (oldsurface and oldsurface.valid) then return end
|
||||
|
||||
-- assuming sea is always default subtype:
|
||||
local seasurface = game.surfaces[memory.sea_name]
|
||||
|
||||
Quest.try_resolve_quest()
|
||||
destination.dynamic_data.quest_type = nil
|
||||
destination.dynamic_data.quest_reward = nil
|
||||
destination.dynamic_data.quest_progress = nil
|
||||
destination.dynamic_data.quest_progressneeded = nil
|
||||
destination.dynamic_data.quest_complete = nil
|
||||
|
||||
-- handle players that were left on the island
|
||||
-- if there is more than one crew on a surface, this will need to be generalised
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if (player.surface == oldsurface) then
|
||||
if player.character and player.character.valid then player.character.die(memory.force) end
|
||||
player.teleport(memory.spawnpoint, seasurface)
|
||||
end
|
||||
end
|
||||
|
||||
destination.dynamic_data = {}
|
||||
|
||||
memory.scripted_biters = nil
|
||||
memory.scripted_unit_groups = nil
|
||||
memory.floating_pollution = nil
|
||||
|
||||
if memory.enemy_force_name then
|
||||
local ef = memory.enemy_force
|
||||
if ef and ef.valid then
|
||||
memory.enemy_force.reset_evolution()
|
||||
local base_evo = Balance.base_evolution_leagues(memory.overworldx)
|
||||
Common.set_evo(base_evo)
|
||||
end
|
||||
end
|
||||
|
||||
game.delete_surface(oldsurface)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- function Public.crowsnest_init_destinations()
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
-- local tiles, entities = {}, {}
|
||||
|
||||
-- Overworld.try_overworld_move{x = 0, y = 0}
|
||||
|
||||
-- -- for _, destination_data in pairs(memory.destinations) do
|
||||
-- -- local iconized_map = SurfacesCommon.fetch_iconized_map(destination_data.destination_index)
|
||||
|
||||
-- -- for _, t in pairs(iconized_map.tiles) do
|
||||
-- -- local x = Crowsnest.platformrightmostedge + destination_data.overworld_position.x + t.position.x
|
||||
-- -- local y = destination_data.overworld_position.y + t.position.y
|
||||
|
||||
-- -- if Math.abs(x) < Crowsnest.Data.width/2 and Math.abs(y) < Crowsnest.Data.height/2 then
|
||||
-- -- tiles[#tiles+1] = {name = t.name, position = {x = x, y = y}}
|
||||
-- -- end
|
||||
-- -- end
|
||||
|
||||
-- -- for _, e in pairs(iconized_map.entities) do
|
||||
-- -- local x = Crowsnest.platformrightmostedge + destination_data.overworld_position.x + e.position.x
|
||||
-- -- local y = destination_data.overworld_position.y + e.position.y
|
||||
-- -- if Math.abs(x) < Crowsnest.Data.width/2 then
|
||||
-- -- local e2 = Utils.deepcopy(e)
|
||||
-- -- e2.position = {x = x, y = y}
|
||||
-- -- entities[#entities+1] = e2
|
||||
-- -- end
|
||||
-- -- end
|
||||
-- -- end
|
||||
-- -- Crowsnest.update_surface(tiles, entities)
|
||||
-- end
|
||||
|
||||
|
||||
function Public.player_goto_crows_nest(player, player_relative_pos)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local surface = game.surfaces[SurfacesCommon.encode_surface_name(memory.id, 0, enum.CROWSNEST, nil)]
|
||||
|
||||
local carpos
|
||||
if player_relative_pos.x < 0 then
|
||||
carpos = {x = -2.29687, y = 0}
|
||||
else
|
||||
carpos = {x = 3.29687, y = 0}
|
||||
end
|
||||
|
||||
local newpos = {x = memory.overworldx + carpos.x - player_relative_pos.x, y = memory.overworldy + carpos.y + player_relative_pos.y}
|
||||
|
||||
local newpos2 = surface.find_non_colliding_position('character', newpos, 5, 0.2) or newpos
|
||||
|
||||
if newpos2 then player.teleport(newpos2, surface) end
|
||||
|
||||
-- player.minimap_enabled = false
|
||||
end
|
||||
|
||||
|
||||
function Public.player_exit_crows_nest(player, player_relative_pos)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface
|
||||
|
||||
if memory.boat and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP) then
|
||||
surface = game.surfaces[SurfacesCommon.encode_surface_name(memory.id, 0, Public.enum.SEA, Public.Sea.enum.DEFAULT)]
|
||||
else
|
||||
surface = game.surfaces[Common.current_destination().surface_name]
|
||||
end
|
||||
|
||||
local carpos
|
||||
if player_relative_pos.x > 0 then
|
||||
carpos = Boats.get_scope(memory.boat).Data.entercrowsnest_cars.right
|
||||
else
|
||||
carpos = Boats.get_scope(memory.boat).Data.entercrowsnest_cars.left
|
||||
end
|
||||
local newpos = {x = memory.boat.position.x + carpos.x - player_relative_pos.x, y = memory.boat.position.y + carpos.y + player_relative_pos.y}
|
||||
|
||||
local newpos2 = surface.find_non_colliding_position('character', newpos, 10, 0.2) or newpos
|
||||
|
||||
if newpos2 then player.teleport(newpos2, surface) end
|
||||
|
||||
-- player.minimap_enabled = true
|
||||
end
|
||||
|
||||
|
||||
function Public.player_goto_hold(player, relative_pos, nth)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
local surface = Hold.get_hold_surface(nth)
|
||||
|
||||
local newpos = {x = Hold.Data.loco_offset.x + 1 + relative_pos.x, y = Hold.Data.loco_offset.y + relative_pos.y}
|
||||
|
||||
local newpos2 = surface.find_non_colliding_position('character', newpos, 5, 0.2) or newpos
|
||||
|
||||
if newpos2 then player.teleport(newpos2, surface) end
|
||||
end
|
||||
|
||||
|
||||
function Public.player_exit_hold(player, relative_pos)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface
|
||||
|
||||
if memory.boat and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP) then
|
||||
surface = game.surfaces[SurfacesCommon.encode_surface_name(memory.id, 0, Public.enum.SEA, Public.Sea.enum.DEFAULT)]
|
||||
else
|
||||
surface = game.surfaces[Common.current_destination().surface_name]
|
||||
end
|
||||
|
||||
local locopos = Boats.get_scope(memory.boat).Data.loco_pos
|
||||
local newpos = {x = memory.boat.position.x + locopos.x + relative_pos.x, y = memory.boat.position.y + locopos.y + relative_pos.y}
|
||||
|
||||
local newpos2 = surface.find_non_colliding_position('character', newpos, 10, 0.2) or newpos
|
||||
|
||||
if newpos2 then player.teleport(newpos2, surface) end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.player_goto_cabin(player, relative_pos)
|
||||
-- local memory = Memory.get_crew_memory()
|
||||
|
||||
local surface = Cabin.get_cabin_surface()
|
||||
|
||||
local newpos = {x = Cabin.Data.car_pos.x - relative_pos.x, y = Cabin.Data.car_pos.y + relative_pos.y}
|
||||
|
||||
local newpos2 = surface.find_non_colliding_position('character', newpos, 5, 0.2) or newpos
|
||||
|
||||
if newpos2 then player.teleport(newpos2, surface) end
|
||||
end
|
||||
|
||||
|
||||
function Public.player_exit_cabin(player, relative_pos)
|
||||
local memory = Memory.get_crew_memory()
|
||||
local surface
|
||||
|
||||
if memory.boat and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP) then
|
||||
surface = game.surfaces[SurfacesCommon.encode_surface_name(memory.id, 0, Public.enum.SEA, Public.Sea.enum.DEFAULT)]
|
||||
else
|
||||
surface = game.surfaces[Common.current_destination().surface_name]
|
||||
end
|
||||
|
||||
local carpos = Boats.get_scope(memory.boat).Data.cabin_car
|
||||
local newpos = {x = memory.boat.position.x + carpos.x - relative_pos.x, y = memory.boat.position.y + carpos.y + relative_pos.y}
|
||||
|
||||
local newpos2 = surface.find_non_colliding_position('character', newpos, 10, 0.2) or newpos
|
||||
|
||||
if newpos2 then player.teleport(newpos2, surface) end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return Public
|
1533
maps/pirates/tick_functions.lua
Normal file
1533
maps/pirates/tick_functions.lua
Normal file
File diff suppressed because it is too large
Load Diff
231
maps/pirates/tick_functions_classes.lua
Normal file
231
maps/pirates/tick_functions_classes.lua
Normal file
@ -0,0 +1,231 @@
|
||||
--luacheck: ignore
|
||||
--luacheck ignores because tickinterval arguments are a code templating choice...
|
||||
|
||||
local Memory = require 'maps.pirates.memory'
|
||||
local Gui = require 'maps.pirates.gui.gui'
|
||||
local Ai = require 'maps.pirates.ai'
|
||||
local Structures = require 'maps.pirates.structures.structures'
|
||||
local Islands = require 'maps.pirates.surfaces.islands.islands'
|
||||
local Boats = require 'maps.pirates.structures.boats.boats'
|
||||
local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
||||
local Interface = require 'maps.pirates.interface'
|
||||
local Roles = require 'maps.pirates.roles.roles'
|
||||
local Classes = require 'maps.pirates.roles.classes'
|
||||
local Progression = require 'maps.pirates.progression'
|
||||
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
|
||||
local Hold = require 'maps.pirates.surfaces.hold'
|
||||
local Cabin = require 'maps.pirates.surfaces.cabin'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local Common = require 'maps.pirates.common'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
local Overworld = require 'maps.pirates.overworld'
|
||||
local Utils = require 'maps.pirates.utils_local'
|
||||
local Crew = require 'maps.pirates.crew'
|
||||
local Math = require 'maps.pirates.math'
|
||||
local _inspect = require 'utils.inspect'.inspect
|
||||
|
||||
local Quest = require 'maps.pirates.quest'
|
||||
|
||||
local Public = {}
|
||||
|
||||
|
||||
function Public.class_renderings(tickinterval)
|
||||
local memory = Memory.get_crew_memory()
|
||||
if not memory.classes_table then return end
|
||||
|
||||
local crew = Common.crew_get_crew_members()
|
||||
|
||||
if not memory.quartermaster_renderings then
|
||||
memory.quartermaster_renderings = {}
|
||||
end
|
||||
|
||||
local processed_renderings = {}
|
||||
|
||||
for _, player in pairs(crew) do
|
||||
local player_index = player.index
|
||||
if memory.classes_table[player_index] == Classes.enum.QUARTERMASTER then
|
||||
local r = memory.quartermaster_renderings[player_index]
|
||||
processed_renderings[player_index] = true
|
||||
if Common.validate_player_and_character(player) then
|
||||
if r and rendering.is_valid(r) then
|
||||
rendering.set_target(r, player.character)
|
||||
else
|
||||
memory.quartermaster_renderings[player_index] = rendering.draw_circle{
|
||||
surface = player.surface,
|
||||
target = player.character,
|
||||
color = CoreData.colors.quartermaster_rendering,
|
||||
filled = false,
|
||||
radius = Common.quartermaster_range,
|
||||
only_in_alt_mode = true,
|
||||
draw_on_ground = true,
|
||||
}
|
||||
end
|
||||
else
|
||||
if r then
|
||||
rendering.destroy(r)
|
||||
memory.quartermaster_renderings[player_index] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for k, r in pairs(memory.quartermaster_renderings) do
|
||||
if not processed_renderings[k] then
|
||||
rendering.destroy(r)
|
||||
memory.quartermaster_renderings[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Public.update_character_properties(tickinterval)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local crew = Common.crew_get_crew_members()
|
||||
|
||||
for _, player in pairs(crew) do
|
||||
if Common.validate_player_and_character(player) then
|
||||
local player_index = player.index
|
||||
local character = player.character
|
||||
if memory.classes_table and memory.classes_table[player_index] then
|
||||
local max_reach_bonus = 0
|
||||
-- if memory.classes_table[player_index] == Classes.enum.DECKHAND then
|
||||
-- max_reach_bonus = Math.max(max_reach_bonus, 6)
|
||||
-- character.character_build_distance_bonus = 6
|
||||
-- else
|
||||
-- character.character_build_distance_bonus = 0
|
||||
-- end
|
||||
|
||||
if memory.classes_table[player_index] == Classes.enum.FISHERMAN then
|
||||
max_reach_bonus = Math.max(max_reach_bonus, 10)
|
||||
character.character_resource_reach_distance_bonus = 10
|
||||
elseif memory.classes_table[player_index] == Classes.enum.MASTER_ANGLER or memory.classes_table[player_index] == Classes.enum.DREDGER then
|
||||
max_reach_bonus = Math.max(max_reach_bonus, 16)
|
||||
character.character_resource_reach_distance_bonus = 16
|
||||
else
|
||||
character.character_resource_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
|
||||
if Common.is_captain(player) then
|
||||
health_boost = health_boost + 50
|
||||
end
|
||||
character.character_health_bonus = health_boost
|
||||
|
||||
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 + 0.75
|
||||
else
|
||||
if memory.classes_table and memory.classes_table[player_index] then
|
||||
local class = memory.classes_table[player_index]
|
||||
if class == Classes.enum.SCOUT then
|
||||
speed_boost = speed_boost + 0.35
|
||||
elseif class == Classes.enum.DECKHAND or class == Classes.enum.BOATSWAIN or class == Classes.enum.SHORESMAN then
|
||||
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 = surfacedata.type == Surfaces.enum.HOLD
|
||||
|
||||
if class == Classes.enum.DECKHAND then
|
||||
if on_ship_bool and (not hold_bool) then
|
||||
speed_boost = speed_boost + 0.25
|
||||
elseif (not on_ship_bool) then
|
||||
speed_boost = speed_boost - 0.25
|
||||
end
|
||||
elseif class == Classes.enum.BOATSWAIN then
|
||||
if hold_bool then
|
||||
speed_boost = speed_boost + 0.25
|
||||
elseif (not on_ship_bool) then
|
||||
speed_boost = speed_boost - 0.25
|
||||
end
|
||||
elseif class == Classes.enum.SHORESMAN then
|
||||
if on_ship_bool then
|
||||
speed_boost = speed_boost - 0.25
|
||||
else
|
||||
speed_boost = speed_boost + 0.07
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
character.character_running_speed_modifier = speed_boost
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.class_rewards_tick(tickinterval)
|
||||
--assuming tickinterval = 6 seconds for now
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
local crew = Common.crew_get_crew_members()
|
||||
for _, player in pairs(crew) do
|
||||
if Common.validate_player_and_character(player) then
|
||||
local player_index = player.index
|
||||
|
||||
if memory.classes_table and memory.classes_table[player_index] then
|
||||
if game.tick % tickinterval == 0 and Common.validate_player_and_character(player) then
|
||||
if memory.classes_table[player.index] == Classes.enum.SMOLDERING then
|
||||
local inv = player.get_inventory(defines.inventory.character_main)
|
||||
if not (inv and inv.valid) then return end
|
||||
local max_coal = 50
|
||||
-- local max_transfer = 1
|
||||
local wood_count = inv.get_item_count('wood')
|
||||
local coal_count = inv.get_item_count('coal')
|
||||
if wood_count >= 1 and coal_count < max_coal then
|
||||
-- local count = Math.min(wood_count, max_coal-coal_count, max_transfer)
|
||||
local count = 1
|
||||
inv.remove({name = 'wood', count = count})
|
||||
inv.insert({name = 'coal', count = count})
|
||||
Common.flying_text_small(player.surface, player.position, '[item=coal]')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if game.tick % tickinterval == 0 and (not (memory.boat and memory.boat.state and memory.boat.state == Structures.Boats.enum_state.ATSEA_LOADING_MAP)) then --it is possible to spend extra time here, so don't give out freebies
|
||||
|
||||
if memory.classes_table and memory.classes_table[player_index] then
|
||||
local class = memory.classes_table[player_index]
|
||||
if 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!
|
||||
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 = surfacedata.type == Surfaces.enum.HOLD
|
||||
|
||||
if class == Classes.enum.DECKHAND and on_ship_bool and (not hold_bool) then
|
||||
Classes.class_ore_grant(player, 4)
|
||||
elseif class == Classes.enum.BOATSWAIN and hold_bool then
|
||||
Classes.class_ore_grant(player, 6)
|
||||
elseif class == Classes.enum.SHORESMAN and (not on_ship_bool) then
|
||||
Classes.class_ore_grant(player, 2)
|
||||
elseif class == Classes.enum.QUARTERMASTER then
|
||||
local nearby_players = #player.surface.find_entities_filtered{position = player.position, radius = Common.quartermaster_range, name = 'character'}
|
||||
|
||||
if nearby_players > 1 then
|
||||
Classes.class_ore_grant(player, nearby_players - 1, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
669
maps/pirates/utils_local.lua
Normal file
669
maps/pirates/utils_local.lua
Normal file
@ -0,0 +1,669 @@
|
||||
|
||||
local Math = require 'maps.pirates.math'
|
||||
-- local _inspect = require 'utils.inspect'.inspect
|
||||
local simplex_noise = require 'utils.simplex_noise'.d2 --rms ~ 0.1925
|
||||
-- local perlin_noise = require 'utils.perlin_noise'
|
||||
-- local Memory = require 'maps.pirates.memory'
|
||||
-- local CoreData = require 'maps.pirates.coredata'
|
||||
local NoisePregen = require 'maps.pirates.noise_pregen.noise_pregen'
|
||||
|
||||
local Public = {}
|
||||
|
||||
-- Lua 5.2 compatibility
|
||||
-- local unpack = unpack or table.unpack
|
||||
|
||||
|
||||
function Public.rgb_from_hsv(h, s, v)
|
||||
-- 0 ≤ H < 360, 0 ≤ S ≤ 1 and 0 ≤ V ≤ 1
|
||||
local r, g, b
|
||||
local c = v * s
|
||||
local x = c * (1 - Math.abs(((h/60) % 2) - 1))
|
||||
local m = v - c
|
||||
if h < 60 then
|
||||
r=c+m
|
||||
g=x+m
|
||||
b=m
|
||||
elseif h < 120 then
|
||||
r=x+m
|
||||
g=c+m
|
||||
b=m
|
||||
elseif h < 180 then
|
||||
r=m
|
||||
g=c+m
|
||||
b=x+m
|
||||
elseif h < 240 then
|
||||
r=m
|
||||
g=x+m
|
||||
b=c+m
|
||||
elseif h < 300 then
|
||||
r=x+m
|
||||
g=m
|
||||
b=c+m
|
||||
else
|
||||
r=c+m
|
||||
g=m
|
||||
b=x+m
|
||||
end
|
||||
return {r = 255*r, g = 255*g, b = 255*b}
|
||||
end
|
||||
|
||||
function Public.stable_sort(list, comp) --sorts but preserves ordering of equals
|
||||
comp = comp or function (a, b) return a < b end
|
||||
|
||||
local num = 0
|
||||
for k, _ in ipairs(list) do
|
||||
num = num + 1
|
||||
end
|
||||
|
||||
if num <= 1 then
|
||||
return
|
||||
end
|
||||
|
||||
local sorted = false
|
||||
local n = num
|
||||
while not sorted do
|
||||
sorted = true
|
||||
for i = 1, n - 1 do
|
||||
if comp(list[i+1], list[i]) then
|
||||
local tmp = list[i]
|
||||
list[i] = list[i+1]
|
||||
list[i+1] = tmp
|
||||
|
||||
sorted = false
|
||||
end
|
||||
end
|
||||
n = n - 1
|
||||
end
|
||||
end
|
||||
|
||||
function Public.psum(plist)
|
||||
local totalx, totaly = 0, 0
|
||||
for i = 1, #plist do
|
||||
if plist[i][1] then --multiplier
|
||||
if plist[i][2] and plist[i][2].x and plist[i][2].y then
|
||||
totalx = totalx + plist[i][1] * plist[i][2].x
|
||||
totaly = totaly + plist[i][1] * plist[i][2].y
|
||||
end
|
||||
elseif plist[i].x and plist[i].y then
|
||||
totalx = totalx + plist[i].x
|
||||
totaly = totaly + plist[i].y
|
||||
end
|
||||
end
|
||||
return {x = totalx, y = totaly}
|
||||
end
|
||||
|
||||
function Public.interpolate(vector1, vector2, param)
|
||||
return {x = vector1.x * (1-param) + vector2.x * param, y = vector1.y * (1-param) + vector2.y * param}
|
||||
end
|
||||
|
||||
function Public.split(s, delimiter)
|
||||
local result = {};
|
||||
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
|
||||
table.insert(result, match);
|
||||
end
|
||||
return result;
|
||||
end
|
||||
|
||||
function Public.contains(table, element)
|
||||
if not table then return false end
|
||||
for _, value in pairs(table) do
|
||||
if value == element then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function Public.snap_coordinates_for_rails(p)
|
||||
return {x = p.x + (p.x % 2) - 1, y = p.y + (p.y % 2)}
|
||||
end
|
||||
|
||||
function Public.spritepath_to_richtext(spritepath)
|
||||
return '[' .. spritepath:gsub("/", "=") .. ']'
|
||||
end
|
||||
|
||||
function Public.nonrepeating_join_dict(t1, t2)
|
||||
t1 = t1 or {}
|
||||
t2 = t2 or {}
|
||||
local t3 = {}
|
||||
for k, i1 in pairs(t1) do
|
||||
t3[k] = i1
|
||||
end
|
||||
for k, i2 in pairs(t2) do
|
||||
t3[k] = i2
|
||||
end
|
||||
return t3
|
||||
end
|
||||
|
||||
function Public.nonrepeating_join(t1, t2)
|
||||
t1 = t1 or {}
|
||||
t2 = t2 or {}
|
||||
local t3 = {}
|
||||
for _, i1 in pairs(t1) do
|
||||
t3[#t3 + 1] = i1
|
||||
end
|
||||
for _, i2 in pairs(t2) do
|
||||
if not Public.contains(t3, i2) then
|
||||
t3[#t3 + 1] = i2
|
||||
end
|
||||
end
|
||||
return t3
|
||||
end
|
||||
|
||||
function Public.exclude(t, t_exclude)
|
||||
t_exclude = t_exclude or {}
|
||||
local t2 = {}
|
||||
for _, i in pairs(t) do
|
||||
if not Public.contains(t_exclude, i) then
|
||||
t2[#t2 + 1] = i
|
||||
end
|
||||
end
|
||||
return t2
|
||||
end
|
||||
|
||||
function Public.exclude_position_arrays(a, b_exclude)
|
||||
b_exclude = b_exclude or {}
|
||||
local a2 = {}
|
||||
for x, xtab in pairs(a) do
|
||||
for y, _ in pairs(xtab) do
|
||||
if not (b_exclude[x] and b_exclude[x][y]) then
|
||||
if not a2[x] then a2[x] = {} end
|
||||
a2[x][y] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return a2
|
||||
end
|
||||
|
||||
function Public.unordered_table_with_values_removed(tbl, val)
|
||||
local to_keep = {}
|
||||
for k, v in pairs(tbl) do
|
||||
if v ~= val then to_keep[k] = v end
|
||||
end
|
||||
return to_keep
|
||||
end
|
||||
|
||||
function Public.ordered_table_with_values_removed(tbl, val)
|
||||
local to_keep = {}
|
||||
local j = 1
|
||||
for i = 1, #tbl do
|
||||
if tbl[i] ~= val then
|
||||
to_keep[j] = tbl[i]
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
return to_keep
|
||||
end
|
||||
|
||||
function Public.ordered_table_with_single_value_removed(tbl, val)
|
||||
local to_keep = {}
|
||||
local j = 1
|
||||
local taken_one = false
|
||||
for i = 1, #tbl do
|
||||
if (tbl[i] ~= val) or taken_one then
|
||||
to_keep[j] = tbl[i]
|
||||
j = j + 1
|
||||
else
|
||||
taken_one = true
|
||||
end
|
||||
end
|
||||
return to_keep
|
||||
end
|
||||
|
||||
function Public.ordered_table_with_index_removed(tbl, index)
|
||||
local to_keep = {}
|
||||
local j = 1
|
||||
for i = 1, #tbl do
|
||||
if i ~= index then
|
||||
to_keep[j] = tbl[i]
|
||||
j = j + 1
|
||||
end
|
||||
end
|
||||
return to_keep
|
||||
end
|
||||
|
||||
function Public.length(tbl)
|
||||
local count = 0
|
||||
for k, _ in pairs(tbl) do
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
function Public.standard_string_form_of_time_in_seconds(time)
|
||||
local time2, str1
|
||||
if time >= 0 then
|
||||
time2 = time
|
||||
str1 = ''
|
||||
else
|
||||
time2 = - time
|
||||
str1 = '-'
|
||||
end
|
||||
local str2
|
||||
local hours = Math.floor(Math.ceil(time2) / 3600)
|
||||
local minutes = Math.floor(Math.ceil(time2) / 60)
|
||||
local seconds = Math.ceil(time2)
|
||||
if hours >= 1 then
|
||||
str2 = string.format('%.0fh %.0fm %.0fs', hours, minutes % 60, seconds % 60)
|
||||
elseif minutes >= 1 then
|
||||
str2 = string.format('%.0fm %.0fs', minutes, seconds % 60)
|
||||
else
|
||||
str2 = string.format('%.0fs', seconds)
|
||||
end
|
||||
return str1 .. str2
|
||||
end
|
||||
|
||||
function Public.time_longform(seconds)
|
||||
local seconds2, str1
|
||||
if seconds >= 0 then
|
||||
seconds2 = seconds
|
||||
str1 = ''
|
||||
else
|
||||
seconds2 = - seconds
|
||||
str1 = '-'
|
||||
end
|
||||
local str2
|
||||
if seconds2 < 60 - 1 then
|
||||
str2 = string.format('%.0f seconds', Math.ceil(seconds2))
|
||||
elseif seconds2 < 60 * 60 - 1 then
|
||||
str2 = string.format('%.0f mins, %.0f seconds', Math.floor(Math.ceil(seconds2) / 60), Math.ceil(seconds2) % 60)
|
||||
elseif seconds2 < 60 * 60 * 24 - 1 then
|
||||
str2 = string.format('%.0f hours, %.0f mins, %.0f seconds', Math.floor(Math.ceil(seconds2) / (60*60)), Math.floor(Math.ceil(seconds2) / 60) % 60, Math.ceil(seconds2) % 60)
|
||||
else
|
||||
str2 = string.format('%.0f days, %.0f hours, %.0f mins, %.0f seconds', Math.floor(Math.ceil(seconds2) / (24*60*60)), Math.floor(Math.ceil(seconds2) / (60*60)) % 24, Math.floor(Math.ceil(seconds2) / 60) % 60, Math.ceil(seconds2) % 60)
|
||||
end
|
||||
return str1 .. str2
|
||||
end
|
||||
|
||||
function Public.time_mediumform(seconds)
|
||||
local seconds2, str1
|
||||
if seconds >= 0 then
|
||||
seconds2 = seconds
|
||||
str1 = ''
|
||||
else
|
||||
seconds2 = - seconds
|
||||
str1 = '-'
|
||||
end
|
||||
local str2
|
||||
local seconds3 = Math.floor(seconds2)
|
||||
if seconds3 < 60 - 1 then
|
||||
str2 = string.format('%.0fs', seconds3)
|
||||
elseif seconds3 < 60 * 60 - 1 then
|
||||
str2 = string.format('%.0fm%.0fs', Math.floor(seconds3 / 60), seconds3 % 60)
|
||||
elseif seconds3 < 60 * 60 * 24 - 1 then
|
||||
str2 = string.format('%.0fh%.0fm%.0fs', Math.floor(seconds3 / (60*60)), Math.floor(seconds3 / 60) % 60, seconds3 % 60)
|
||||
else
|
||||
str2 = string.format('%.0fd%.0fh%.0fm%.0fs', Math.floor(seconds3 / (24*60*60)), Math.floor(seconds3 / (60*60)) % 24, Math.floor(seconds3 / 60) % 60, seconds3 % 60)
|
||||
end
|
||||
return str1 .. str2
|
||||
end
|
||||
|
||||
function Public.deepcopy(obj) --doesn't copy metatables
|
||||
if type(obj) ~= 'table' then return obj end
|
||||
local res = {}
|
||||
for k, v in pairs(obj) do res[Public.deepcopy(k)] = Public.deepcopy(v) end
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
function Public.bignumber_abbrevform(number) --e.g. 516, 1.2k, 21.4k, 137k
|
||||
local str1, str2, number2
|
||||
if number >= 0 then
|
||||
number2 = number
|
||||
str1 = ''
|
||||
else
|
||||
number2 = - number
|
||||
str1 = '-'
|
||||
end
|
||||
|
||||
if number2 == 0 then
|
||||
str2 = '0'
|
||||
elseif number2 < 1000 then
|
||||
str2 = string.format('%.0d', Math.floor(number2))
|
||||
elseif number2 < 100000 then
|
||||
str2 = string.format('%.1fk', Math.floor(number2/100)/10)
|
||||
else
|
||||
str2 = string.format('%.0dk', Math.floor(number2/1000))
|
||||
end
|
||||
|
||||
return str1 .. str2
|
||||
end
|
||||
function Public.bignumber_abbrevform2(number) --e.g. 516, 1.2k, 21k, 137k
|
||||
local str1, str2, number2
|
||||
if number >= 0 then
|
||||
number2 = number
|
||||
str1 = ''
|
||||
else
|
||||
number2 = - number
|
||||
str1 = '-'
|
||||
end
|
||||
|
||||
if number2 == 0 then
|
||||
str2 = '0'
|
||||
elseif number2 < 1000 then
|
||||
str2 = string.format('%.0d', Math.floor(number2))
|
||||
elseif number2 < 10000 then
|
||||
str2 = string.format('%.1fk', Math.floor(number2/100)/10)
|
||||
else
|
||||
str2 = string.format('%.0dk', Math.floor(number2/1000))
|
||||
end
|
||||
|
||||
return str1 .. str2
|
||||
end
|
||||
function Public.negative_rate_abbrevform(number)
|
||||
local str1, str2, number2
|
||||
if number > 0 then
|
||||
number2 = number
|
||||
str1 = ''
|
||||
else
|
||||
number2 = - number
|
||||
str1 = '-'
|
||||
end
|
||||
if number2 == 0 then
|
||||
str2 = '0'
|
||||
elseif number2 < 10 then
|
||||
str2 = string.format('%.1f', Math.ceil(number2*10)/10)
|
||||
else
|
||||
str2 = string.format('%.0d', Math.ceil(number2))
|
||||
end
|
||||
|
||||
return str1 .. str2 .. '/s'
|
||||
end
|
||||
|
||||
|
||||
function Public.noise_field_simplex_2d(noise_data, seed, normalised)
|
||||
normalised = normalised or false
|
||||
|
||||
local f = function(position)
|
||||
local noise, _seed, weight_sum = 0, seed, 0
|
||||
for i = 1, #noise_data do
|
||||
local n = noise_data[i]
|
||||
local toadd = n.amplitude
|
||||
if n.wavelength > 0 then --=0 codes for infinite
|
||||
toadd = toadd * simplex_noise(position.x / n.wavelength, position.y / n.wavelength, _seed)
|
||||
_seed = _seed + 12345 --some deficiencies
|
||||
end
|
||||
|
||||
if normalised then weight_sum = weight_sum + n.amplitude end
|
||||
noise = noise + toadd
|
||||
end
|
||||
if normalised then noise = noise / weight_sum end
|
||||
return noise
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.hardcoded_noise_field_decompress(fieldtype, noise_data, seed, normalised)
|
||||
normalised = normalised or false
|
||||
|
||||
-- local hardcoded_upperscale = NoisePregen[fieldtype].upperscale
|
||||
-- local hardcoded_boxsize = NoisePregen[fieldtype].boxsize
|
||||
local hardcoded_wordlength = NoisePregen[fieldtype].wordlength
|
||||
local factor = NoisePregen[fieldtype].factor
|
||||
|
||||
local f = function(position)
|
||||
local noise, weight_sum, _seed = 0, 0, seed
|
||||
for i = 1, #noise_data do
|
||||
local n = noise_data[i]
|
||||
local toadd = n.amplitude
|
||||
local seedfactor = n.seedfactor or 1
|
||||
|
||||
if n.upperscale > 0 then --=0 codes for infinite
|
||||
local scale = n.upperscale / 100
|
||||
|
||||
local seed2 = seed * seedfactor
|
||||
|
||||
local x2 = position.x / scale
|
||||
local y2 = position.y / scale
|
||||
|
||||
local x2remainder = x2%1
|
||||
local y2remainder = y2%1
|
||||
|
||||
local x2floor = x2 - x2remainder
|
||||
local y2floor = y2 - y2remainder
|
||||
|
||||
local topleftnoiseindex = seed2 % (1000*1000)
|
||||
|
||||
local relativeindex00 = x2floor + y2floor * 1000
|
||||
|
||||
local totalindex00 = (topleftnoiseindex + relativeindex00) % (1000*1000)
|
||||
local totalindex10 = (1 + topleftnoiseindex + relativeindex00) % (1000*1000)
|
||||
local totalindex01 = (1000 + topleftnoiseindex + relativeindex00) % (1000*1000)
|
||||
|
||||
local strindex00 = 1 + totalindex00 * hardcoded_wordlength
|
||||
local strindex10 = 1 + totalindex10 * hardcoded_wordlength
|
||||
local strindex01 = 1 + totalindex01 * hardcoded_wordlength
|
||||
|
||||
local str00 = NoisePregen[fieldtype].Data:sub(strindex00, strindex00 + (hardcoded_wordlength - 1))
|
||||
local str10 = NoisePregen[fieldtype].Data:sub(strindex10, strindex10 + (hardcoded_wordlength - 1))
|
||||
local str01 = NoisePregen[fieldtype].Data:sub(strindex01, strindex01 + (hardcoded_wordlength - 1))
|
||||
local noise00, noise10, noise01 = 0, 0, 0
|
||||
for j = 0, hardcoded_wordlength-1 do
|
||||
noise00 = noise00 + NoisePregen.dec[str00:sub(hardcoded_wordlength - j, hardcoded_wordlength - j)] * (NoisePregen.encoding_length ^ j)
|
||||
noise10 = noise10 + NoisePregen.dec[str10:sub(hardcoded_wordlength - j, hardcoded_wordlength - j)] * (NoisePregen.encoding_length ^ j)
|
||||
noise01 = noise01 + NoisePregen.dec[str01:sub(hardcoded_wordlength - j, hardcoded_wordlength - j)] * (NoisePregen.encoding_length ^ j)
|
||||
end
|
||||
|
||||
if noise00 % 2 == 1 then noise00 = -noise00 end
|
||||
noise00 = noise00 / (NoisePregen.encoding_length ^ (hardcoded_wordlength-1))
|
||||
|
||||
if noise10 % 2 == 1 then noise10 = -noise10 end
|
||||
noise10 = noise10 / (NoisePregen.encoding_length ^ (hardcoded_wordlength-1))
|
||||
|
||||
if noise01 % 2 == 1 then noise01 = -noise01 end
|
||||
noise01 = noise01 / (NoisePregen.encoding_length ^ (hardcoded_wordlength-1))
|
||||
|
||||
-- local hardnoise00 = tonumber(strsub00:sub(2,6))/10000
|
||||
-- if strsub00:sub(1,1) == '-' then hardnoise00 = -hardnoise00 end
|
||||
-- local hardnoise10 = tonumber(strsub10:sub(2,6))/10000
|
||||
-- if strsub10:sub(1,1) == '-' then hardnoise10 = -hardnoise10 end
|
||||
-- local hardnoise01 = tonumber(strsub01:sub(2,6))/10000
|
||||
-- if strsub01:sub(1,1) == '-' then hardnoise01 = -hardnoise01 end
|
||||
|
||||
-- log(_inspect{topleftnoiseindex, topleftnoiseindex2, relativeindex00, relativeindex10, relativeindex01})
|
||||
-- log(_inspect{strindex00, strindex10, strindex01, hardnoise1, hardnoise2, hardnoise3})
|
||||
|
||||
local interpolatedhardnoise = noise00 + x2remainder*(noise10-noise00) + y2remainder*(noise01-noise00)
|
||||
|
||||
toadd = toadd * factor * tonumber(interpolatedhardnoise)
|
||||
_seed = _seed + 12345
|
||||
end
|
||||
|
||||
if normalised then weight_sum = weight_sum + n.amplitude end
|
||||
noise = noise + toadd
|
||||
end
|
||||
if normalised then noise = noise / weight_sum end
|
||||
return noise
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.hardcoded_noise_field(fieldtype, noise_data, seed, normalised)
|
||||
normalised = normalised or false
|
||||
|
||||
-- local hardcoded_upperscale = NoisePregen[fieldtype].upperscale --100
|
||||
-- local hardcoded_boxsize = NoisePregen[fieldtype].boxsize --1000
|
||||
local hardcoded_wordlength = NoisePregen[fieldtype].wordlength
|
||||
local factor = NoisePregen[fieldtype].factor
|
||||
|
||||
local f = function(position)
|
||||
local noise, weight_sum, _seed = 0, 0, seed
|
||||
for i = 1, #noise_data do
|
||||
local n = noise_data[i]
|
||||
local toadd = n.amplitude
|
||||
local seedfactor = n.seedfactor or 1
|
||||
|
||||
if n.upperscale > 0 then --=0 codes for infinite
|
||||
local scale = n.upperscale / 100
|
||||
|
||||
local seed2 = seed * seedfactor
|
||||
|
||||
local x2 = position.x / scale
|
||||
local y2 = position.y / scale
|
||||
|
||||
local x2remainder = x2%1
|
||||
local y2remainder = y2%1
|
||||
|
||||
local x2floor = x2 - x2remainder
|
||||
local y2floor = y2 - y2remainder
|
||||
|
||||
local seedindex = seed2 % (1000*1000)
|
||||
|
||||
local relativeindex00 = x2floor + y2floor * 1000
|
||||
|
||||
local noiseindex1 = seedindex + relativeindex00
|
||||
|
||||
local totalindex00 = noiseindex1 % (1000*1000)
|
||||
local totalindex10 = (1 + noiseindex1) % (1000*1000)
|
||||
local totalindex01 = (1000 + noiseindex1) % (1000*1000)
|
||||
|
||||
local strindex00 = 1 + totalindex00 * hardcoded_wordlength
|
||||
local strindex10 = 1 + totalindex10 * hardcoded_wordlength
|
||||
local strindex01 = 1 + totalindex01 * hardcoded_wordlength
|
||||
|
||||
local str00 = NoisePregen[fieldtype].Data:sub(strindex00, strindex00 + (hardcoded_wordlength - 1))
|
||||
local str10 = NoisePregen[fieldtype].Data:sub(strindex10, strindex10 + (hardcoded_wordlength - 1))
|
||||
local str01 = NoisePregen[fieldtype].Data:sub(strindex01, strindex01 + (hardcoded_wordlength - 1))
|
||||
|
||||
local noise00 = tonumber(str00:sub(2,6))/10000
|
||||
if str00:sub(1,1) == '-' then noise00 = -noise00 end
|
||||
local noise10 = tonumber(str10:sub(2,6))/10000
|
||||
if str10:sub(1,1) == '-' then noise10 = -noise10 end
|
||||
local noise01 = tonumber(str01:sub(2,6))/10000
|
||||
if str01:sub(1,1) == '-' then noise01 = -noise01 end
|
||||
|
||||
-- log(_inspect{topleftnoiseindex, topleftnoiseindex2, relativeindex00, relativeindex10, relativeindex01})
|
||||
-- log(_inspect{strindex00, strindex10, strindex01, hardnoise1, hardnoise2, hardnoise3})
|
||||
|
||||
local interpolatedhardnoise = noise00 + x2remainder*(noise10-noise00) + y2remainder*(noise01-noise00)
|
||||
|
||||
toadd = toadd * factor * tonumber(interpolatedhardnoise)
|
||||
_seed = _seed + 12345 --some deficiencies
|
||||
end
|
||||
|
||||
if normalised then weight_sum = weight_sum + n.amplitude end
|
||||
noise = noise + toadd
|
||||
end
|
||||
if normalised then noise = noise / weight_sum end
|
||||
return noise
|
||||
end
|
||||
return f
|
||||
end
|
||||
|
||||
|
||||
|
||||
function Public.noise_generator(noiseparams, seed)
|
||||
--memoizes locally
|
||||
noiseparams = noiseparams or {}
|
||||
seed = seed or 0
|
||||
|
||||
local ret = {}
|
||||
for k, v in pairs(noiseparams) do
|
||||
local fn
|
||||
if v.type == 'simplex_2d' then
|
||||
fn = Public.noise_field_simplex_2d(v.params, seed, v.normalised)
|
||||
elseif v.type == 'perlin_1d_circle' then
|
||||
fn = Public.noise_field_perlin_1d_circle(v.params, seed, v.normalised)
|
||||
else
|
||||
fn = Public.hardcoded_noise_field(v.type, v.params, seed, v.normalised)
|
||||
end
|
||||
ret[k] = Public.memoize(fn)
|
||||
end
|
||||
|
||||
function ret:addNoise(key, new_noise_function)
|
||||
if self[key] then return
|
||||
else
|
||||
self[key] = Public.memoize(new_noise_function)
|
||||
end
|
||||
end
|
||||
ret.seed = seed
|
||||
-- ret.noiseparams = noiseparams
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
local function cache_get(cache, params)
|
||||
local node = cache
|
||||
for i=1, #params do
|
||||
node = node.children and node.children[params[i]]
|
||||
if not node then return nil end
|
||||
end
|
||||
return node.results
|
||||
end
|
||||
|
||||
local function cache_put(cache, params, results)
|
||||
local node = cache
|
||||
local param
|
||||
for i=1, #params do
|
||||
param = params[i]
|
||||
node.children = node.children or {}
|
||||
node.children[param] = node.children[param] or {}
|
||||
node = node.children[param]
|
||||
end
|
||||
node.results = results
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- The following functions were adapted from https://github.com/kikito/memoize.lua/blob/master/memoize.lua, under the MIT License:
|
||||
-- [[
|
||||
-- MIT LICENSE
|
||||
-- Copyright (c) 2018 Enrique García Cota
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-- copy of this software and associated documentation files (the
|
||||
-- "Software"), to deal in the Software without restriction, including
|
||||
-- without limitation the rights to use, copy, modify, merge, publish,
|
||||
-- distribute, sublicense, and/or sell copies of the Software, and to
|
||||
-- permit persons to whom the Software is furnished to do so, subject to
|
||||
-- the following conditions:
|
||||
-- The above copyright notice and this permission notice shall be included
|
||||
-- in all copies or substantial portions of the Software.
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
-- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
-- ]]
|
||||
|
||||
local function is_callable(f)
|
||||
local tf = type(f)
|
||||
if tf == 'function' then return true end
|
||||
if tf == 'table' then
|
||||
local mt = getmetatable(f)
|
||||
return type(mt) == 'table' and is_callable(mt.__call)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- == memoization
|
||||
-- memoize takes in a function and outputs an auto-memoizing version of the same
|
||||
-- e.g. local memoized_f = memoize(f, <cache>), explicit cache is optional
|
||||
function Public.memoize(f, cache)
|
||||
cache = cache or {}
|
||||
|
||||
if not is_callable(f) then
|
||||
log(string.format(
|
||||
"Only functions and callable tables are memoizable. Received %s (a %s)",
|
||||
tostring(f), type(f)))
|
||||
end
|
||||
|
||||
return function (...)
|
||||
local params = {...}
|
||||
|
||||
local results = cache_get(cache, params)
|
||||
if not results then
|
||||
results = { f(...) }
|
||||
cache_put(cache, params, results)
|
||||
end
|
||||
|
||||
return table.unpack(results)
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
Loading…
x
Reference in New Issue
Block a user