mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-28 03:57:22 +02:00
Bug fixes and tweaks
Changes: - It's darker in the cabin and holds now. - Slightly decreased amount of time you can stay in Maze island. - Slightly decreased Nightmare difficulty index. - Slightly increased amount of biters that spawn in Red Desert. - Biters in Red Desert island now spawn every 5 mins instead of every 6 mins. - Fixed an issue where some classes like Scout or Samurai would heal themselves when getting splashed by grenades instead of getting damaged. - Fixed an issue where obstacle boxes in hold could spawn on top of substations. - Fixed an issue where players could get teleported around for no reason when boat was undocking.
This commit is contained in:
parent
087ed90bb2
commit
7e32ea3a77
@ -237,7 +237,7 @@ class_definition_for=Class definition for
|
||||
|
||||
class_deckhand=Deckhand
|
||||
# class_deckhand_explanation=They move faster and generate ore for the cabin whilst onboard above deck.
|
||||
class_deckhand_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst onboard above deck. No ore is generated while at sea.
|
||||
class_deckhand_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst onboard above deck.\nNo ore is generated while at sea.
|
||||
class_fisherman=Fisherman
|
||||
# class_fisherman_explanation=They fish at greater distance.
|
||||
class_fisherman_explanation_advanced=They fish at greater distance (__1__ extra tile range), and catch more (+__2__ fish).
|
||||
@ -255,7 +255,7 @@ class_shoresman=Shoresman
|
||||
class_shoresman_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst offboard.
|
||||
class_boatswain=Boatswain
|
||||
# class_boatswain_explanation=They move faster and generate ore for the cabin whilst below deck.
|
||||
class_boatswain_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst below deck. No ore is generated while at sea.
|
||||
class_boatswain_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) for the cabin whilst below deck.\nNo ore is generated while at sea.
|
||||
class_prospector=Prospector
|
||||
# class_prospector_explanation=They find more resources when handmining.
|
||||
class_prospector_explanation_advanced=They find more resources when handmining.
|
||||
@ -279,7 +279,7 @@ class_iron_leg=Iron Leg
|
||||
class_iron_leg_explanation_advanced=They receive __1__% less damage when carrying at least __2__ iron ore.
|
||||
class_quartermaster=Quartermaster
|
||||
# class_quartermaster_explanation=Nearby crewmates get +10% physical attack and generate ore for the cabin.
|
||||
class_quartermaster_explanation_advanced=Nearby crewmates (at __1__ tile radius) get +__2__% physical attack bonus and generate ore for the cabin (ore amount depends on nearby crewmate count). No ore is generated while at sea.
|
||||
class_quartermaster_explanation_advanced=Nearby crewmates (at __1__ tile radius) get +__2__% physical attack bonus and generate ore for the cabin (ore amount depends on nearby crewmate count).\nNo ore is generated while at sea.
|
||||
class_dredger=Dredger
|
||||
# class_dredger_explanation=They find surprising items when they fish.
|
||||
class_dredger_explanation_advanced=They can grab fish from an insane distance (__1__ extra tile range), and catch more (+__2__ fish). In addition, they find surprising items when fishing.
|
||||
|
@ -449,6 +449,7 @@ local function damage_dealt_by_players_changes(event)
|
||||
if not event.cause.valid then return end
|
||||
if not event.entity.valid then return end
|
||||
if event.cause.name ~= 'character' then return end
|
||||
if event.entity.name == 'character' then return end
|
||||
|
||||
local character = event.cause
|
||||
local player = character.player
|
||||
@ -459,78 +460,78 @@ local function damage_dealt_by_players_changes(event)
|
||||
local player_index = player.index
|
||||
local class = Classes.get_class(player_index)
|
||||
|
||||
if class and class == Classes.enum.SCOUT and event.final_health > 0 then --lethal damage must be unaffected
|
||||
event.entity.health = event.entity.health + (1 - Balance.scout_damage_dealt_multiplier) * event.final_damage_amount
|
||||
elseif class and (class == Classes.enum.SAMURAI or class == Classes.enum.HATAMOTO) then
|
||||
local samurai = class == Classes.enum.SAMURAI
|
||||
local hatamoto = class == Classes.enum.HATAMOTO
|
||||
-- Lethal damage must be unaffected, otherwise enemy will never die.
|
||||
-- @Future reference: when implementing damage changes for mobs with healthbar, make this check with healthbar health too
|
||||
if event.final_health > 0 then
|
||||
if class and class == Classes.enum.SCOUT then
|
||||
event.entity.health = event.entity.health + (1 - Balance.scout_damage_dealt_multiplier) * event.final_damage_amount
|
||||
elseif class and (class == Classes.enum.SAMURAI or class == Classes.enum.HATAMOTO) then
|
||||
local samurai = class == Classes.enum.SAMURAI
|
||||
local hatamoto = class == Classes.enum.HATAMOTO
|
||||
|
||||
--==Note this! (what the hell is this)
|
||||
if not (samurai or hatamoto) then return end
|
||||
local no_weapon = (not (character.get_inventory(defines.inventory.character_guns) and character.get_inventory(defines.inventory.character_guns)[character.selected_gun_index] and character.get_inventory(defines.inventory.character_guns)[character.selected_gun_index].valid_for_read))
|
||||
|
||||
local no_weapon = (not (character.get_inventory(defines.inventory.character_guns) and character.get_inventory(defines.inventory.character_guns)[character.selected_gun_index] and character.get_inventory(defines.inventory.character_guns)[character.selected_gun_index].valid_for_read))
|
||||
local melee = (physical or acid) and no_weapon
|
||||
|
||||
local melee = (physical or acid) and no_weapon
|
||||
local extra_damage_to_deal = 0
|
||||
|
||||
local extra_damage_to_deal = 0
|
||||
local big_number = 1000
|
||||
|
||||
local big_number = 1000
|
||||
local extra_physical_damage_from_research_multiplier = 1 + memory.force.get_ammo_damage_modifier('bullet')
|
||||
|
||||
local extra_physical_damage_from_research_multiplier = 1 + memory.force.get_ammo_damage_modifier('bullet')
|
||||
|
||||
if melee and event.final_health > 0 then
|
||||
if physical then
|
||||
if samurai then
|
||||
extra_damage_to_deal = Balance.samurai_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
|
||||
elseif hatamoto then
|
||||
extra_damage_to_deal = Balance.hatamoto_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
|
||||
if melee then
|
||||
if physical then
|
||||
if samurai then
|
||||
extra_damage_to_deal = Balance.samurai_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
|
||||
elseif hatamoto then
|
||||
extra_damage_to_deal = Balance.hatamoto_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
|
||||
end
|
||||
elseif acid then --this hacky stuff is to implement repeated spillover splash damage, whilst getting around the fact that if ovekill damage takes something to zero health, we can't tell in that event how much double-overkill damage should be dealt by reading off its HP. This code assumes that characters only deal acid damage via this function.
|
||||
extra_damage_to_deal = event.original_damage_amount * big_number
|
||||
end
|
||||
elseif acid then --this hacky stuff is to implement repeated spillover splash damage, whilst getting around the fact that if ovekill damage takes something to zero health, we can't tell in that event how much double-overkill damage should be dealt by reading off its HP. This code assumes that characters only deal acid damage via this function.
|
||||
extra_damage_to_deal = event.original_damage_amount * big_number
|
||||
end
|
||||
elseif (not melee) and event.final_health > 0 then
|
||||
if samurai then
|
||||
event.entity.health = event.entity.health + (1 - Balance.samurai_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
|
||||
elseif hatamoto then
|
||||
event.entity.health = event.entity.health + (1 - Balance.hatamoto_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
|
||||
end
|
||||
end
|
||||
|
||||
if extra_damage_to_deal > 0 then
|
||||
if event.entity.health >= extra_damage_to_deal then
|
||||
event.entity.damage(extra_damage_to_deal, character.force, 'impact', character) --using .damage rather than subtracting from health directly plays better with entities which use healthbars
|
||||
else
|
||||
local surplus = (extra_damage_to_deal - event.entity.health)*0.8
|
||||
event.entity.die(character.force, character)
|
||||
local nearest = player.surface.find_nearest_enemy{position = player.position, max_distance = 2, force = player.force}
|
||||
if nearest and nearest.valid then
|
||||
nearest.damage(surplus/big_number, character.force, 'acid', character)
|
||||
if samurai then
|
||||
event.entity.health = event.entity.health + (1 - Balance.samurai_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
|
||||
elseif hatamoto then
|
||||
event.entity.health = event.entity.health + (1 - Balance.hatamoto_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if physical then
|
||||
|
||||
-- QUARTERMASTER BUFFS
|
||||
local nearby_players = player.surface.find_entities_filtered{position = player.position, radius = Balance.quartermaster_range, type = {'character'}}
|
||||
|
||||
for _, p2 in pairs(nearby_players) do
|
||||
if p2.player and p2.player.valid then
|
||||
local p2_index = p2.player.index
|
||||
if event.entity.valid and player_index ~= p2_index and Classes.get_class(p2_index) == Classes.enum.QUARTERMASTER then
|
||||
event.entity.damage((Balance.quartermaster_bonus_physical_damage - 1) * event.final_damage_amount, character.force, 'impact', character) --triggers this function again, but not physical this time
|
||||
if extra_damage_to_deal > 0 then
|
||||
if event.entity.health >= extra_damage_to_deal then
|
||||
event.entity.damage(extra_damage_to_deal, character.force, 'impact', character) --using .damage rather than subtracting from health directly plays better with entities which use healthbars
|
||||
else
|
||||
local surplus = (extra_damage_to_deal - event.entity.health)*0.8
|
||||
event.entity.die(character.force, character)
|
||||
local nearest = player.surface.find_nearest_enemy{position = player.position, max_distance = 2, force = player.force}
|
||||
if nearest and nearest.valid then
|
||||
nearest.damage(surplus/big_number, character.force, 'acid', character)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if physical then
|
||||
|
||||
-- PISTOL BUFFS
|
||||
if character.shooting_state.state ~= defines.shooting.not_shooting then
|
||||
local weapon = character.get_inventory(defines.inventory.character_guns)[character.selected_gun_index]
|
||||
local ammo = character.get_inventory(defines.inventory.character_ammo)[character.selected_gun_index]
|
||||
if event.entity.valid and weapon.valid_for_read and ammo.valid_for_read and weapon.name == 'pistol' and (ammo.name == 'firearm-magazine' or ammo.name == 'piercing-rounds-magazine' or ammo.name == 'uranium-rounds-magazine') then
|
||||
event.entity.damage(event.final_damage_amount * (Balance.pistol_damage_multiplier() - 1), character.force, 'impact', character) --triggers this function again, but not physical this time
|
||||
-- QUARTERMASTER BUFFS
|
||||
local nearby_players = player.surface.find_entities_filtered{position = player.position, radius = Balance.quartermaster_range, type = {'character'}}
|
||||
|
||||
for _, p2 in pairs(nearby_players) do
|
||||
if p2.player and p2.player.valid then
|
||||
local p2_index = p2.player.index
|
||||
if event.entity.valid and player_index ~= p2_index and Classes.get_class(p2_index) == Classes.enum.QUARTERMASTER then
|
||||
event.entity.damage((Balance.quartermaster_bonus_physical_damage - 1) * event.final_damage_amount, character.force, 'impact', character) --triggers this function again, but not physical this time
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- PISTOL BUFFS
|
||||
if character.shooting_state.state ~= defines.shooting.not_shooting then
|
||||
local weapon = character.get_inventory(defines.inventory.character_guns)[character.selected_gun_index]
|
||||
local ammo = character.get_inventory(defines.inventory.character_ammo)[character.selected_gun_index]
|
||||
if event.entity.valid and weapon.valid_for_read and ammo.valid_for_read and weapon.name == 'pistol' and (ammo.name == 'firearm-magazine' or ammo.name == 'piercing-rounds-magazine' or ammo.name == 'uranium-rounds-magazine') then
|
||||
event.entity.damage(event.final_damage_amount * (Balance.pistol_damage_multiplier() - 1), character.force, 'impact', character) --triggers this function again, but not physical this time
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -81,6 +81,7 @@ Public.doctor_heal_radius = 20
|
||||
Public.doctor_heal_percentage_amount = 0.15
|
||||
Public.shaman_energy_required_per_summon = 1000000
|
||||
Public.shaman_max_charge = 30000000
|
||||
Public.shaman_summoned_biter_time_to_live = 60 * 5 -- in seconds
|
||||
|
||||
Public.class_cycle_count = 5 -- How many classes should be purchased to have a chance to buy the same class again
|
||||
|
||||
@ -206,8 +207,8 @@ function Public.max_time_on_island(island_subtype)
|
||||
|
||||
if x == 40 then -- it's important for this island to be somewhat chill, so that it's not such a shock to go here from the first lobby chill island
|
||||
time = time * 1.2
|
||||
elseif island_subtype == IslandEnum.enum.MAZE then --more time
|
||||
time = time * 1.05
|
||||
-- elseif island_subtype == IslandEnum.enum.MAZE then --more time
|
||||
-- time = time * 1.05
|
||||
elseif island_subtype == IslandEnum.enum.CAVE then -- supposed to be chill island
|
||||
time = time * 0.9
|
||||
elseif island_subtype == IslandEnum.enum.RED_DESERT then --this island has big amount of resources so rather high risk (need time to mine resources) and high reward (lots of iron/copper/stone)
|
||||
|
@ -1215,6 +1215,7 @@ if _DEBUG then
|
||||
player.insert{name='steel-chest', count = 50}
|
||||
player.insert{name='express-loader', count = 50}
|
||||
player.insert{name='burner-inserter', count = 50}
|
||||
player.insert{name='accumulator', count = 50}
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -123,11 +123,11 @@ Public.difficulty_options = {
|
||||
--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.5, icon = 'item/firearm-magazine', text = {'pirates.difficulty_easy'}, associated_color = {r = 50, g = 255, b = 50}},
|
||||
|
||||
{value = 0.95, icon = 'item/piercing-rounds-magazine', text = {'pirates.difficulty_normal'}, associated_color = {r = 255, g = 255, b = 50}},
|
||||
{value = 1.0, icon = 'item/piercing-rounds-magazine', text = {'pirates.difficulty_normal'}, associated_color = {r = 255, g = 255, b = 50}},
|
||||
|
||||
{value = 1.5, icon = 'item/uranium-rounds-magazine', text = {'pirates.difficutly_hard'}, associated_color = {r = 255, g = 50, b = 50}},
|
||||
|
||||
{value = 2.2, icon = 'item/atomic-bomb', text = {'pirates.difficulty_nightmare'}, associated_color = {r = 170, g = 60, b = 60}},
|
||||
{value = 2.0, icon = 'item/atomic-bomb', text = {'pirates.difficulty_nightmare'}, associated_color = {r = 170, g = 60, b = 60}},
|
||||
}
|
||||
function Public.get_difficulty_option_from_value(difficulty_value)
|
||||
-- given a difficulty value, key in to the closesy entry in the above table. (organising things this way allows us to make changes to the 'value' keys in the above table without disrupting e.g. past highscores data)
|
||||
|
@ -718,6 +718,8 @@ function Public.initialise_crew(accepted_proposal)
|
||||
memory.class_renderings = {}
|
||||
memory.class_auxiliary_data = {}
|
||||
|
||||
memory.pet_biters = {}
|
||||
|
||||
memory.hold_surface_count = 1
|
||||
|
||||
memory.speed_boost_characters = {}
|
||||
|
@ -234,9 +234,9 @@ function Public.generate_destination_base_cost_to_undock(p, subtype)
|
||||
['uranium-235'] = Math.ceil(Math.ceil(80 + (macro_p.x - 1))),
|
||||
-- ['uranium-235'] = Math.ceil(Math.ceil(80 + (macro_p.x)/2)), --tried adding beacons instead of this
|
||||
}
|
||||
elseif subtype == IslandEnum.enum.RED_DESERT then
|
||||
elseif subtype == IslandEnum.enum.RED_DESERT or subtype == IslandEnum.enum.CAVE then
|
||||
if base_cost_to_undock and base_cost_to_undock['launch_rocket'] == true then
|
||||
base_cost_to_undock['launch_rocket'] = false -- some extra variety
|
||||
base_cost_to_undock['launch_rocket'] = false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -469,29 +469,37 @@ local function class_on_player_used_capsule(event)
|
||||
end
|
||||
end
|
||||
elseif class == Public.enum.SHAMAN then
|
||||
local data = memory.class_auxiliary_data[player.index]
|
||||
if data and data.shaman_charge then
|
||||
for _ = 1, 3 do
|
||||
if data.shaman_charge < Balance.shaman_energy_required_per_summon then break end
|
||||
local player_surface_type = SurfacesCommon.decode_surface_name(player.surface.name).type
|
||||
|
||||
local pos = Math.vector_sum(player.position, Math.random_vec(2))
|
||||
local name = Common.get_random_unit_type(Math.clamp(0, 1, memory.evolution_factor))
|
||||
if player_surface_type == SurfacesCommon.enum.ISLAND or player_surface_type == SurfacesCommon.enum.SEA then
|
||||
local data = memory.class_auxiliary_data[player.index]
|
||||
if data and data.shaman_charge then
|
||||
for _ = 1, 2 do
|
||||
if data.shaman_charge < Balance.shaman_energy_required_per_summon then break end
|
||||
|
||||
if player.surface.can_place_entity{name = name, position = pos, force = memory.force} then
|
||||
local e = player.surface.create_entity{name = name, position = pos, force = memory.force}
|
||||
if e and e.valid then
|
||||
data.shaman_charge = data.shaman_charge - Balance.shaman_energy_required_per_summon
|
||||
rendering.draw_text {
|
||||
text = '~' .. player.name .. "'s minion~",
|
||||
surface = player.surface,
|
||||
target = e,
|
||||
target_offset = {0, -2.6},
|
||||
color = player.force.color,
|
||||
scale = 1.05,
|
||||
font = 'default-large-semibold',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
local spawn_range = 2
|
||||
local pos = Math.vector_sum(player.position, Math.random_vec(spawn_range))
|
||||
local name = Common.get_random_unit_type(Math.clamp(0, 1, memory.evolution_factor))
|
||||
local spawn_pos = player.surface.find_non_colliding_position(name, pos, spawn_range + 1, 0.5)
|
||||
|
||||
if spawn_pos then
|
||||
local e = player.surface.create_entity{name = name, position = spawn_pos, force = memory.force}
|
||||
if e and e.valid then
|
||||
data.shaman_charge = data.shaman_charge - Balance.shaman_energy_required_per_summon
|
||||
rendering.draw_text {
|
||||
text = '~' .. player.name .. "'s minion~",
|
||||
surface = player.surface,
|
||||
target = e,
|
||||
target_offset = {0, -2.6},
|
||||
color = player.force.color,
|
||||
scale = 1.05,
|
||||
font = 'default-large-semibold',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
|
||||
memory.pet_biters[e.unit_number] = {pet_owner = player, pet = e, time_to_live = Balance.shaman_summoned_biter_time_to_live}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -337,11 +337,11 @@ 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 (not memory.run_is_protected) then
|
||||
-- in this case, lose captainhood
|
||||
local non_afk_members = Common.crew_get_nonafk_crew_members()
|
||||
|
||||
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])
|
||||
if Common.is_captain(player) and (not memory.run_is_protected) and #non_afk_members >= 1 then
|
||||
if #non_afk_members == 1 then --don't need to bounce it around
|
||||
Public.make_captain(non_afk_members[1])
|
||||
else
|
||||
local force = memory.force
|
||||
if force and force.valid then
|
||||
|
@ -849,118 +849,162 @@ local function process_entity_on_boat_unteleportable(memory, boat, newsurface, v
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- @TODO: Rocket silo that is prepared to launch the rocket needs to be cloned with clone_entities instead. See: https://forums.factorio.com/viewtopic.php?f=23&t=105073&p=580968
|
||||
local function process_entity_on_boat_teleportable(memory, boat, newsurface, newposition, vector, oldsurface_name, newsurface_name, electric_pole_neighbours_matrix, circuit_neighbours_matrix, e)
|
||||
|
||||
if oldsurface_name == newsurface_name then
|
||||
e.teleport(vector.x, vector.y)
|
||||
e.update_connections()
|
||||
else
|
||||
local p = Utils.deepcopy(e.position)
|
||||
local p2 = {x = p.x + vector.x, y = p.y + vector.y}
|
||||
return
|
||||
end
|
||||
|
||||
if e.type == 'electric-pole' then
|
||||
for k, v in pairs(e.neighbours or {}) do
|
||||
if k == 'copper' then --red and green cases handled by circuit_neighbours_matrix
|
||||
if not electric_pole_neighbours_matrix[k] then electric_pole_neighbours_matrix[k] = {} end
|
||||
for _, v2 in pairs(v) do
|
||||
if v2 and v2.valid and v2.position then
|
||||
local v2p = v2.position
|
||||
if not electric_pole_neighbours_matrix[k][v2p.x] then
|
||||
electric_pole_neighbours_matrix[k][v2p.x] = {}
|
||||
end
|
||||
if not electric_pole_neighbours_matrix[k][v2p.x][v2p.y] then
|
||||
electric_pole_neighbours_matrix[k][v2p.x][v2p.y] = {}
|
||||
end
|
||||
electric_pole_neighbours_matrix[k][v2p.x][v2p.y][#electric_pole_neighbours_matrix[k][v2p.x][v2p.y] + 1] = {name = e.name, pos = p}
|
||||
|
||||
local p = Utils.deepcopy(e.position)
|
||||
local p2 = {x = p.x + vector.x, y = p.y + vector.y}
|
||||
|
||||
if e.type == 'electric-pole' then
|
||||
for k, v in pairs(e.neighbours or {}) do
|
||||
if k == 'copper' then --red and green cases handled by circuit_neighbours_matrix
|
||||
if not electric_pole_neighbours_matrix[k] then electric_pole_neighbours_matrix[k] = {} end
|
||||
for _, v2 in pairs(v) do
|
||||
if v2 and v2.valid and v2.position then
|
||||
local v2p = v2.position
|
||||
if not electric_pole_neighbours_matrix[k][v2p.x] then
|
||||
electric_pole_neighbours_matrix[k][v2p.x] = {}
|
||||
end
|
||||
if not electric_pole_neighbours_matrix[k][v2p.x][v2p.y] then
|
||||
electric_pole_neighbours_matrix[k][v2p.x][v2p.y] = {}
|
||||
end
|
||||
electric_pole_neighbours_matrix[k][v2p.x][v2p.y][#electric_pole_neighbours_matrix[k][v2p.x][v2p.y] + 1] = {name = e.name, pos = p}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, v in pairs(e.circuit_connection_definitions or {}) do
|
||||
local e2 = v.target_entity
|
||||
local wire = v.wire
|
||||
local source_circuit_id = v.source_circuit_id
|
||||
local target_circuit_id = v.target_circuit_id
|
||||
if e2 and e2.valid and e2.position and (wire == defines.wire_type.red or wire == defines.wire_type.green) then --observed an error "Expected source_wire_id for entities with more than one wire connection" in the .connect_neighbour() function called later, so putting the red/green wire check in to try and catch it
|
||||
local e2p = e2.position
|
||||
if not circuit_neighbours_matrix[e2p.x] then
|
||||
circuit_neighbours_matrix[e2p.x] = {}
|
||||
end
|
||||
if not circuit_neighbours_matrix[e2p.x][e2p.y] then
|
||||
circuit_neighbours_matrix[e2p.x][e2p.y] = {}
|
||||
end
|
||||
circuit_neighbours_matrix[e2p.x][e2p.y][#circuit_neighbours_matrix[e2p.x][e2p.y] + 1] = {name = e.name, pos = p, wire = wire, source_circuit_id = target_circuit_id, target_circuit_id = source_circuit_id} --flip since we will read these backwards
|
||||
for _, v in pairs(e.circuit_connection_definitions or {}) do
|
||||
local e2 = v.target_entity
|
||||
local wire = v.wire
|
||||
local source_circuit_id = v.source_circuit_id
|
||||
local target_circuit_id = v.target_circuit_id
|
||||
if e2 and e2.valid and e2.position and (wire == defines.wire_type.red or wire == defines.wire_type.green) then --observed an error "Expected source_wire_id for entities with more than one wire connection" in the .connect_neighbour() function called later, so putting the red/green wire check in to try and catch it
|
||||
local e2p = e2.position
|
||||
if not circuit_neighbours_matrix[e2p.x] then
|
||||
circuit_neighbours_matrix[e2p.x] = {}
|
||||
end
|
||||
end
|
||||
|
||||
-- Special case for vehicles, because currently they can be exclusively teleported between surfaces
|
||||
local ee
|
||||
if e.name == 'car' or e.name == 'tank' or e.name == 'spidertron' then
|
||||
e.teleport(p2, newsurface)
|
||||
else
|
||||
if string.sub(e.name, 1, 14) ~= 'spidertron-leg' then
|
||||
ee = e.clone{position = p2, surface = newsurface, create_build_effect_smoke = false}
|
||||
if not circuit_neighbours_matrix[e2p.x][e2p.y] then
|
||||
circuit_neighbours_matrix[e2p.x][e2p.y] = {}
|
||||
end
|
||||
circuit_neighbours_matrix[e2p.x][e2p.y][#circuit_neighbours_matrix[e2p.x][e2p.y] + 1] = {name = e.name, pos = p, wire = wire, source_circuit_id = target_circuit_id, target_circuit_id = source_circuit_id} --flip since we will read these backwards
|
||||
end
|
||||
end
|
||||
|
||||
if e == boat.upstairs_pole then
|
||||
boat.upstairs_pole = ee
|
||||
if boat.downstairs_poles and boat.downstairs_poles[1] then
|
||||
-- Remove previous connection, before connecting it with the new clone to avoid sometimes having to remove wire connection because of limit
|
||||
e.disconnect_neighbour(boat.downstairs_poles[1][1])
|
||||
Common.force_connect_poles(boat.upstairs_pole, boat.downstairs_poles[1][1])
|
||||
end
|
||||
-- Special case for vehicles, because currently they can be exclusively teleported between surfaces
|
||||
local ee
|
||||
if e.name == 'car' or e.name == 'tank' or e.name == 'spidertron' then
|
||||
e.teleport(p2, newsurface)
|
||||
else
|
||||
if string.sub(e.name, 1, 14) ~= 'spidertron-leg' then
|
||||
ee = e.clone{position = p2, surface = newsurface, create_build_effect_smoke = false}
|
||||
end
|
||||
end
|
||||
|
||||
-- We don't want to destroy spidertron leg, because otherwise it will destroy whole spidertron. Funny huh?
|
||||
if not (e.name == 'car' or e.name == 'tank' or e.name == 'spidertron' or string.sub(e.name, 1, 14) == 'spidertron-leg') then
|
||||
e.destroy()
|
||||
if e == boat.upstairs_pole then
|
||||
boat.upstairs_pole = ee
|
||||
if boat.downstairs_poles and boat.downstairs_poles[1] then
|
||||
-- Remove previous connection, before connecting it with the new clone to avoid sometimes having to remove wire connection because of limit
|
||||
e.disconnect_neighbour(boat.downstairs_poles[1][1])
|
||||
Common.force_connect_poles(boat.upstairs_pole, boat.downstairs_poles[1][1])
|
||||
end
|
||||
end
|
||||
|
||||
-- Right now in the game we don't expect any non-player characters, so let's kill them to make a point:
|
||||
if ee and ee.valid and ee.name == 'character' and (not ee.player) then
|
||||
ee.die()
|
||||
|
||||
local pet_biter_data = memory.pet_biters[e.unit_number]
|
||||
if pet_biter_data then
|
||||
local owner = pet_biter_data.pet_owner
|
||||
rendering.draw_text {
|
||||
text = '~' .. owner.name .. "'s minion~",
|
||||
surface = newsurface,
|
||||
target = ee,
|
||||
target_offset = {0, -2.6},
|
||||
color = owner.force.color,
|
||||
scale = 1.05,
|
||||
font = 'default-large-semibold',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
memory.pet_biters[ee.unit_number] = {pet_owner = owner, pet = ee, time_to_live = pet_biter_data.time_to_live}
|
||||
memory.pet_biters[e.unit_number] = nil
|
||||
end
|
||||
|
||||
-- We don't want to destroy spidertron leg, because otherwise it will destroy whole spidertron. Funny huh?
|
||||
if not (e.name == 'car' or e.name == 'tank' or e.name == 'spidertron' or string.sub(e.name, 1, 14) == 'spidertron-leg') then
|
||||
e.destroy()
|
||||
end
|
||||
|
||||
-- Right now in the game we don't expect any non-player characters, so let's kill them to make a point:
|
||||
if ee and ee.valid and ee.name == 'character' and (not ee.player) then
|
||||
ee.die()
|
||||
end
|
||||
|
||||
if not (ee and ee.valid and ee.name) then
|
||||
return
|
||||
end
|
||||
|
||||
if ee.name == 'blue-chest' then
|
||||
if p2.y < newposition.y then
|
||||
memory.boat.decksteeringchests.left = ee
|
||||
-- --attach parrot to this:
|
||||
-- if boat.parrot then
|
||||
-- local r = rendering.draw_sprite{
|
||||
-- sprite = "file/parrot/parrot_idle_fly_1.png",
|
||||
-- surface = newsurface,
|
||||
-- target = ee,
|
||||
-- target_offset = Utils.psum{boat.parrot.position_relative_to_boat, boat.parrot.sprite_extra_offset},
|
||||
-- x_scale = 2.8,
|
||||
-- y_scale = 2.8,
|
||||
-- }
|
||||
-- local r2 = rendering.draw_text{
|
||||
-- text = 'Parrot',
|
||||
-- color = CoreData.colors.parrot,
|
||||
-- surface = newsurface,
|
||||
-- target = ee,
|
||||
-- target_offset = Utils.psum{boat.parrot.position_relative_to_boat, boat.parrot.text_extra_offset},
|
||||
-- alignment = 'center',
|
||||
-- }
|
||||
-- rendering.destroy(boat.parrot.render)
|
||||
-- rendering.destroy(boat.parrot.render_name)
|
||||
-- boat.parrot.frame = 1
|
||||
-- boat.parrot.state = Parrot.enum.FLY
|
||||
-- boat.parrot.render = r
|
||||
-- boat.parrot.render_name = r2
|
||||
-- end
|
||||
elseif p2.y > newposition.y then
|
||||
memory.boat.decksteeringchests.right = ee
|
||||
end
|
||||
end
|
||||
|
||||
if ee and ee.valid and ee.name then
|
||||
if ee.name == 'blue-chest' then
|
||||
if p2.y < newposition.y then
|
||||
memory.boat.decksteeringchests.left = ee
|
||||
-- --attach parrot to this:
|
||||
-- if boat.parrot then
|
||||
-- local r = rendering.draw_sprite{
|
||||
-- sprite = "file/parrot/parrot_idle_fly_1.png",
|
||||
-- surface = newsurface,
|
||||
-- target = ee,
|
||||
-- target_offset = Utils.psum{boat.parrot.position_relative_to_boat, boat.parrot.sprite_extra_offset},
|
||||
-- x_scale = 2.8,
|
||||
-- y_scale = 2.8,
|
||||
-- }
|
||||
-- local r2 = rendering.draw_text{
|
||||
-- text = 'Parrot',
|
||||
-- color = CoreData.colors.parrot,
|
||||
-- surface = newsurface,
|
||||
-- target = ee,
|
||||
-- target_offset = Utils.psum{boat.parrot.position_relative_to_boat, boat.parrot.text_extra_offset},
|
||||
-- alignment = 'center',
|
||||
-- }
|
||||
-- rendering.destroy(boat.parrot.render)
|
||||
-- rendering.destroy(boat.parrot.render_name)
|
||||
-- boat.parrot.frame = 1
|
||||
-- boat.parrot.state = Parrot.enum.FLY
|
||||
-- boat.parrot.render = r
|
||||
-- boat.parrot.render_name = r2
|
||||
-- end
|
||||
elseif p2.y > newposition.y then
|
||||
memory.boat.decksteeringchests.right = ee
|
||||
if circuit_neighbours_matrix[p.x] and circuit_neighbours_matrix[p.x][p.y] then
|
||||
for _, v2 in pairs(circuit_neighbours_matrix[p.x][p.y]) do
|
||||
local p3 = {x = v2.pos.x + vector.x, y = v2.pos.y + vector.y}
|
||||
local e3s = newsurface.find_entities_filtered{
|
||||
name = v2.name,
|
||||
position = p3,
|
||||
radius = 0.01,
|
||||
}
|
||||
if e3s and #e3s>0 then
|
||||
local e3 = e3s[1]
|
||||
if e3 and e3.valid then
|
||||
ee.connect_neighbour{wire = v2.wire, target_entity = e3, source_circuit_id = v2.source_circuit_id, target_circuit_id = v2.target_circuit_id}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if circuit_neighbours_matrix[p.x] and circuit_neighbours_matrix[p.x][p.y] then
|
||||
for _, v2 in pairs(circuit_neighbours_matrix[p.x][p.y]) do
|
||||
if ee.type == 'electric-pole' then
|
||||
for k, v in pairs(electric_pole_neighbours_matrix or {}) do
|
||||
if v[p.x] and v[p.x][p.y] then
|
||||
for _, v2 in pairs(v[p.x][p.y]) do
|
||||
local p3 = {x = v2.pos.x + vector.x, y = v2.pos.y + vector.y}
|
||||
local e3s = newsurface.find_entities_filtered{
|
||||
name = v2.name,
|
||||
@ -970,33 +1014,12 @@ local function process_entity_on_boat_teleportable(memory, boat, newsurface, new
|
||||
if e3s and #e3s>0 then
|
||||
local e3 = e3s[1]
|
||||
if e3 and e3.valid then
|
||||
ee.connect_neighbour{wire = v2.wire, target_entity = e3, source_circuit_id = v2.source_circuit_id, target_circuit_id = v2.target_circuit_id}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if ee.type and ee.type == 'electric-pole' then
|
||||
for k, v in pairs(electric_pole_neighbours_matrix or {}) do
|
||||
if v[p.x] and v[p.x][p.y] then
|
||||
for _, v2 in pairs(v[p.x][p.y]) do
|
||||
local p3 = {x = v2.pos.x + vector.x, y = v2.pos.y + vector.y}
|
||||
local e3s = newsurface.find_entities_filtered{
|
||||
name = v2.name,
|
||||
position = p3,
|
||||
radius = 0.01,
|
||||
}
|
||||
if e3s and #e3s>0 then
|
||||
local e3 = e3s[1]
|
||||
if e3 and e3.valid then
|
||||
if k == 'copper' then
|
||||
ee.connect_neighbour(e3)
|
||||
-- elseif k == 'red' then
|
||||
-- ee.connect_neighbour{wire = defines.wire_type.red, target_entity = e3}
|
||||
-- elseif k == 'green' then
|
||||
-- ee.connect_neighbour{wire = defines.wire_type.green, target_entity = e3}
|
||||
end
|
||||
end
|
||||
if k == 'copper' then
|
||||
ee.connect_neighbour(e3)
|
||||
-- elseif k == 'red' then
|
||||
-- ee.connect_neighbour{wire = defines.wire_type.red, target_entity = e3}
|
||||
-- elseif k == 'green' then
|
||||
-- ee.connect_neighbour{wire = defines.wire_type.green, target_entity = e3}
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1088,7 +1111,7 @@ local function teleport_handle_wake_tiles(boat, dummyboat, newsurface_name, olds
|
||||
-- NOTE: this will need to be changed, when ship doesn't necessarily arrive from the left
|
||||
if vector.x < 0 then
|
||||
for _, player in pairs(Common.crew_get_crew_members()) do
|
||||
if player.character and player.character.valid then
|
||||
if player.character and player.character.valid and player.surface.name == oldsurface_name then
|
||||
local tile = oldsurface.get_tile(player.character.position.x, player.character.position.y)
|
||||
if tile.valid then
|
||||
if Utils.contains(CoreData.water_tile_names, tile.name) then
|
||||
@ -1101,7 +1124,6 @@ local function teleport_handle_wake_tiles(boat, dummyboat, newsurface_name, olds
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
local p = dummyboat.position
|
||||
|
@ -168,7 +168,7 @@ function Public.create_cabin_surface()
|
||||
|
||||
local surface = game.create_surface(cabinname, map_gen_settings)
|
||||
surface.freeze_daytime = true
|
||||
surface.daytime = 0
|
||||
surface.daytime = 0.3
|
||||
surface.show_clouds = false
|
||||
|
||||
-- more here
|
||||
|
@ -127,7 +127,7 @@ function Public.create_hold_surface(nth)
|
||||
|
||||
local surface = game.create_surface(holdname, map_gen_settings)
|
||||
surface.freeze_daytime = true
|
||||
surface.daytime = 0
|
||||
surface.daytime = 0.3
|
||||
surface.show_clouds = false
|
||||
surface.solar_power_multiplier = 0
|
||||
|
||||
@ -184,20 +184,6 @@ function Public.create_hold_surface(nth)
|
||||
|
||||
Common.build_small_loco(surface, Public.Data.loco_offset, memory.force, {255, 106, 52})
|
||||
|
||||
-- We place obstacle boxes before the other static boxes, so that they are potentially one tile closer to the edge than they would be otherwise:
|
||||
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] = 6, [3] = 5, [4] = 2}, items)
|
||||
-- Public.hold_place_random_obstacle_boxes(nth, {[1] = 0, [2] = 9, [3] = 3, [4] = 1}, items)
|
||||
|
||||
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
|
||||
|
||||
if not boat.downstairs_poles then boat.downstairs_poles = {} end
|
||||
boat.downstairs_poles[nth] = {}
|
||||
for i = 1, #Public.Data.downstairs_pole_positions do
|
||||
@ -225,6 +211,20 @@ function Public.create_hold_surface(nth)
|
||||
end
|
||||
end
|
||||
|
||||
-- We place obstacle boxes before the other static boxes, so that they are potentially one tile closer to the edge than they would be otherwise:
|
||||
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] = 6, [3] = 5, [4] = 2}, items)
|
||||
-- Public.hold_place_random_obstacle_boxes(nth, {[1] = 0, [2] = 9, [3] = 3, [4] = 1}, items)
|
||||
|
||||
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
|
||||
|
||||
if subtype == enum.SECONDARY then
|
||||
local difficulty_name = CoreData.get_difficulty_option_informal_name_from_value(memory.difficulty)
|
||||
if difficulty_name == 'nightmare' then
|
||||
|
@ -10,6 +10,7 @@ local BoatData = require 'maps.pirates.structures.boats.sloop.data'
|
||||
local Event = require 'utils.event'
|
||||
local IslandEnum = require 'maps.pirates.surfaces.islands.island_enum'
|
||||
local Balance = require 'maps.pirates.balance'
|
||||
local CoreData = require 'maps.pirates.coredata'
|
||||
|
||||
local Public = {}
|
||||
Public.Data = require 'maps.pirates.surfaces.islands.cave.data'
|
||||
@ -100,6 +101,8 @@ function Public.reveal(cave_miner, surface, source_surface, position, brushsize)
|
||||
destination.dynamic_data.disabled_wave_timer = Balance.prevent_waves_from_spawning_in_cave_timer_length
|
||||
end
|
||||
|
||||
Public.try_make_spawner_elite(e, destination)
|
||||
|
||||
Public.reveal(cave_miner, surface, source_surface, entity_position, 15)
|
||||
end
|
||||
end
|
||||
@ -111,6 +114,22 @@ function Public.reveal(cave_miner, surface, source_surface, position, brushsize)
|
||||
source_surface.request_to_generate_chunks(position, 3)
|
||||
end
|
||||
|
||||
function Public.try_make_spawner_elite(spawner, destination)
|
||||
local memory = Memory.get_crew_memory()
|
||||
|
||||
if spawner and CoreData.get_difficulty_option_from_value(memory.difficulty) >= 3 then
|
||||
if Math.random(20) == 1 then
|
||||
local max_health = Balance.elite_spawner_health()
|
||||
Common.new_healthbar(true, spawner, max_health, nil, max_health, 0.8, nil, destination.dynamic_data)
|
||||
|
||||
local elite_spawners = destination.dynamic_data.elite_spawners
|
||||
if elite_spawners then
|
||||
elite_spawners[#elite_spawners + 1] = spawner
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Public.roll_source_surface(destination_data)
|
||||
local map_gen_settings = {
|
||||
|
@ -233,7 +233,7 @@ local function red_desert_tick()
|
||||
|
||||
Public.underground_worms_ai()
|
||||
|
||||
if game.tick % 360 == 0 and destination.dynamic_data.timer and destination.dynamic_data.timer > 60 then
|
||||
if game.tick % 300 == 0 and destination.dynamic_data.timer and destination.dynamic_data.timer > 60 then
|
||||
Public.custom_biter_ai()
|
||||
end
|
||||
end
|
||||
@ -387,7 +387,7 @@ function Public.custom_biter_ai()
|
||||
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 unittype_pollutioncost = CoreData.biterPollutionValues[name] * Balance.scripted_biters_pollution_cost_multiplier()
|
||||
|
||||
local function spawn(name2)
|
||||
units_created_count = units_created_count + 1
|
||||
|
@ -83,7 +83,7 @@ function Public.terrain(args)
|
||||
else
|
||||
args.tiles[#args.tiles + 1] = {name = 'water-shallow', position = p}
|
||||
|
||||
if math.random(1, 1024) == 1 then
|
||||
if math.random(1, 512) == 1 then
|
||||
local name = Common.get_random_worm_type(memory.evolution_factor)
|
||||
local force = memory.enemy_force_name
|
||||
args.entities[#args.entities + 1] = {name = name, position = p, force = force}
|
||||
|
Loading…
x
Reference in New Issue
Block a user