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

Merge branch 'develop' into develop

This commit is contained in:
Gerkiz 2023-07-29 19:56:31 +02:00 committed by GitHub
commit c16265fb8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 590 additions and 327 deletions

View File

@ -16,7 +16,7 @@ softmod_info_tips_1=Features of the game that are hard to work out alone
softmod_info_tips_2=• The captain can steer the boat from the crow's nest by placing 50 rail signals in one of the blue boxes.\n• Resources granted to the ship appear in the captain's cabin.\n• Charging a silo drains power from everything else on its network.\n• The quantity of ore available on an island is independent of the order in which you break rocks.\n• Passive pollution ramps up over time on each island.\n• The strength of attacks is proportional to the number of remaining nests. (The time-based rate of evolution is proportional to nests too, but destroying a nest will immediately jump evolution by most of the amount it 'would have' made had it survived.)\n• item-on-ground entities on the deck are moved to the cabin when the boat moves, for performance reasons.\n• Commands: /ccolor gives you a fun color. /classinfo {classname} gives the description of the named class. To manage your class, use /take {classname} or /giveup.
softmod_info_updates_1=Significant recent changes
softmod_info_updates_2=v1.5.1\n• Greatly increased biter wave sizes on harder difficulties.\n• Reduced amount of resources and rewards that can be acquired. However all rewards (such as plates from chests and coin rewards from launching rocket) now scale with leagues.\n• Possible fix for some desync cases.\n• Bugfixes.\n\nv1.5.0\n• Enabled a lot more researches.\n• New elite biters and spawners for hard+ difficulties.\n• Added new classes: Medic, Doctor and Shaman.\n• Disabled old classes: Gourmet, Deckhand, Boatswain.\n• More than one class of same type can be acquired now. Same classes now can be offered again every 5 class purchases.\n• Mining trees now have a chance to spawn smol ore vein or chest with loot.\n• Balance changes, tweaks and more!
softmod_info_updates_2=v1.5.2\n• Elite biters now also appear in Easy/Normal difficulties from league 800.\n• Elite biters now also spawn 4 non-elite biters on death.\n• When player rejoins the game within 1 minute, he will spawn where he was when he left, instead of on the boat.\n• "Kovarex-enrichment-process" recipe is now researched by default\n• Bugfixes.\n\nv1.5.1\n• Greatly increased biter wave sizes on harder difficulties.\n• Reduced amount of resources and rewards that can be acquired. However all rewards (such as plates from chests and coin rewards from launching rocket) now scale with leagues.\n• Possible fix for some desync cases.\n• Bugfixes.
softmod_info_credits_1=Credits
softmod_info_credits_2=Pirate Ship designed and coded by thesixthroc. Updates from Piratux. Comfy codebase and help from Gerkiz, Hanakocz and Mew @ Comfy Industries (https://getcomfy.eu). Some island structure blueprints contributed by Mattisso.\n\nCome chat with us: https://getcomfy.eu/discord\n\n"Those white gloves. I'll never forget them 'till the day I die." - Dr. John
@ -236,58 +236,40 @@ class_unobtainable=Class was disabled and is unobtainable.
class_definition_for=Class definition for
class_deckhand=Deckhand
# class_deckhand_explanation=They move faster and generate ore whilst onboard above deck.
class_deckhand_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) 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).
class_scout=Scout
# class_scout_explanation=They are faster, but frail and deal less damage.
class_scout_explanation_advanced=They move __1__% times faster, but receive __2__% more damage and deal __3__% less damage.
class_samurai=Samurai
# class_samurai_explanation=They are tough, and *with no weapon equipped* fight well by melee, but poorly otherwise.
class_samurai_explanation_advanced=They receive __1__% less damage, and with no weapon equipped do extra __2__ damage in melee (scales with 'physical projectile damage' research bonuses), but deal __3__% less damage otherwise.\nIf the damage dealt in melee is an overkill, the remaining damage splashes onto nearby enemies.
class_merchant=Merchant
# class_merchant_explanation=They generate 50 doubloons per league.
class_merchant_explanation_advanced=They generate 50 doubloons per league.
class_shoresman=Shoresman
# class_shoresman_explanation=They move slightly faster and generate ore whilst offboard.
class_shoresman_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) whilst offboard.
class_boatswain=Boatswain
# class_boatswain_explanation=They move faster and generate ore whilst below deck.
class_boatswain_explanation_advanced=They move __1__% times faster and generate ore (+__2__ every __3__ seconds) 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.
class_lumberjack=Lumberjack
# class_lumberjack_explanation=They find more resources when chopping trees.
class_lumberjack_explanation_advanced=They find ores and more coins when chopping trees.
class_master_angler=Master Angler
# class_master_angler_explanation=They fish at much greater distance, and catch more.
class_master_angler_explanation_advanced=They fish at much greater distance (__1__ extra tile range), and catch more (+__2__ fish and +__3__ coins).
class_wood_lord=Lord of the Woods
# class_wood_lord_explanation=They find many more resources when chopping trees.
class_wood_lord_explanation_advanced=They find many more resources when chopping trees.
class_chief_excavator=Chief Excavator
# class_chief_excavator_explanation=They find many more resources when handmining.
class_chief_excavator_explanation_advanced=They find many more resources when handmining.
class_hatamoto=Hatamoto
# class_hatamoto_explanation=They are very tough, and *with no weapon equipped* fight well by melee, but poorly otherwise.
class_hatamoto_explanation_advanced=They receive __1__% less damage, and with no weapon equipped do extra __2__ damage in melee (scales with 'physical projectile damage' research bonuses), but deal __3__% less damage otherwise.\n\nIf the damage dealt in melee is an overkill, the remaining damage splashes onto nearby enemies.
class_iron_leg=Iron Leg
# class_iron_leg_explanation=They are very resistant to damage when carrying 3000 iron ore.
class_iron_leg_explanation_advanced=They receive __1__% less damage when carrying at least __2__ iron ore.
class_quartermaster=Quartermaster
# class_quartermaster_explanation=Nearby crewmates get +10% physical attack and generate ore.
class_quartermaster_explanation_advanced=Nearby crewmates (at __1__ tile radius) get +__2__% physical attack bonus and generate ore (ore amount depends on nearby crewmate count).\nNo ore is generated while at sea.
class_quartermaster_explanation_advanced= You and your nearby crewmates (at __1__ tile radius) get +__2__% physical attack bonus and generate ore (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.
class_smoldering=Smoldering
# class_smoldering_explanation=They periodically convert wood into coal, if they have less than 50 coal.
class_smoldering_explanation_advanced=They periodically convert wood into coal, if they have less than 50 coal.
class_gourmet=Gourmet
# class_gourmet_explanation=They generate ore by eating fish in fancy locations.
class_gourmet_explanation_advanced=They generate ore by eating fish in fancy locations. Does not generate ore while at sea.
class_chef=Chef
class_chef_explanation_advanced=They cook meat of defeated enemies and turn it into something tasty.

View File

@ -133,6 +133,8 @@ function Public.wave_size_rng() -- random variance in attack sizes
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
local rng_scale = Balance.crew_scale()^(1/4) -- slightly dampen wave variance for small crews as they can't handle it
-- prevent situation where when player reveals spawner, he immediately gets surrounded by massive amount of biters (especially late game)
if destination and destination.type == SurfacesCommon.enum.ISLAND then
if destination.dynamic_data and destination.dynamic_data.disabled_wave_timer and destination.dynamic_data.disabled_wave_timer > 0 then
@ -144,17 +146,18 @@ function Public.wave_size_rng() -- random variance in attack sizes
local wave_size_multiplier = 1
local rng1 = Math.random(100)
if rng1 > wave_percentage_chance then
wave_size_multiplier = 0
elseif memory.overworldx > 0 then
local rng2 = Math.random(1000)
if rng2 <= 890 then
if rng2 >= 110 * rng_scale then
wave_size_multiplier = 1
elseif rng2 <= 970 then
elseif rng2 >= 30 * rng_scale then
wave_size_multiplier = 1.5
elseif rng2 <= 985 then
elseif rng2 >= 15 * rng_scale then
wave_size_multiplier = 2
elseif rng2 <= 995 then
elseif rng2 >= 5 * rng_scale then
wave_size_multiplier = 3
else
wave_size_multiplier = 4
@ -902,7 +905,39 @@ function Public.try_boat_biters_attack()
end
local function on_entity_destroyed(event)
local registration_number = event.registration_number
local p
local biter_name
local surface_name
local memory
for i = 1,3 do
Memory.set_working_id(i)
memory = Memory.get_crew_memory()
if memory.elite_biters_stream_registrations then
for j, r in pairs(memory.elite_biters_stream_registrations) do
if r.number == registration_number then
p = r.position
biter_name = r.biter_name
surface_name = r.surface_name
memory.elite_biters_stream_registrations = Utils.ordered_table_with_index_removed(memory.elite_biters_stream_registrations, j)
break
end
end
end
if p then break end
end
if p then
local surface = game.surfaces[surface_name]
if not (surface and surface.valid) then return end
local p2 = surface.find_non_colliding_position('medium-biter', p, 10, 0.2)
if not p2 then return end
surface.create_entity{name = biter_name, position = p2, force = memory.enemy_force_name}
end
end
-- function Public.destroy_inactive_scripted_biters()
@ -921,5 +956,8 @@ end
--=== Data
local event = require 'utils.event'
event.add(defines.events.on_entity_destroyed, on_entity_destroyed)
return Public

View File

@ -109,17 +109,23 @@ local function biters_chew_stuff_faster(event)
if not (event.cause and event.cause.valid and event.cause.force and event.cause.force.name and event.entity and event.entity.valid and event.entity.force and event.entity.force.name) then return end
if event.cause.force.name ~= memory.enemy_force_name then return end --Enemy Forces only
-- @TODO: "event.entity.force.index == 3" looks suspicious (and probably doesn't work?), investigate it
if (event.entity.force.index == 3 or event.entity.force.name == 'environment') then
event.entity.health = event.entity.health - event.final_damage_amount * 5
event.final_damage_amount = event.final_damage_amount * 6
if destination and destination.type == Surfaces.enum.ISLAND and destination.subtype == IslandEnum.enum.MAZE then
event.entity.health = event.entity.health - event.final_damage_amount * 10
event.entity.health = event.entity.health - event.final_damage_amount
event.final_damage_amount = event.final_damage_amount * 2
end
elseif event.entity.name == 'pipe' then
event.entity.health = event.entity.health - event.final_damage_amount * 0.5
event.final_damage_amount = event.final_damage_amount * 1.5
elseif event.entity.name == 'stone-furnace' then
event.entity.health = event.entity.health - event.final_damage_amount * 0.5
event.final_damage_amount = event.final_damage_amount * 1.5
elseif event.entity.name == 'wooden-chest' or event.entity.name == 'stone-chest' or event.entity.name == 'steel-chest' then
event.entity.health = event.entity.health - event.final_damage_amount * 0.5
event.final_damage_amount = event.final_damage_amount * 1.5
end
end
@ -202,7 +208,7 @@ local function damage_to_enemyboat_spawners(event)
if eb.spawner and eb.spawner.valid and event.entity == eb.spawner then
-- if eb.spawner and eb.spawner.valid and event.entity == eb.spawner and eb.state == Structures.Boats.enum_state.APPROACHING then
local damage = event.final_damage_amount
local remaining_health = Common.entity_damage_healthbar(event.entity, damage, destination.dynamic_data)
local remaining_health = Common.entity_damage_healthbar(event.entity, damage)
if remaining_health and remaining_health <= 0 then
event.entity.die()
@ -228,7 +234,7 @@ local function damage_to_elite_spawners(event)
if spawner and spawner.valid and event.entity == spawner then
local damage = event.final_damage_amount
local remaining_health = Common.entity_damage_healthbar(event.entity, damage, destination.dynamic_data)
local remaining_health = Common.entity_damage_healthbar(event.entity, damage)
if remaining_health and remaining_health <= 0 then
event.entity.die()
@ -253,7 +259,6 @@ local function damage_to_elite_biters(event)
local remaining_health = Common.entity_damage_healthbar(event.entity, damage)
if remaining_health and remaining_health <= 0 then
memory.elite_biters[event.entity.unit_number] = nil
event.entity.die()
end
end
@ -306,29 +311,27 @@ local function damage_to_krakens(event)
if not (surface_name == memory.sea_name) then return end
local unit_number = event.entity.unit_number
local damage = event.final_damage_amount
local adjusted_damage = damage
if event.damage_type.name and event.damage_type.name == 'poison' then
adjusted_damage = adjusted_damage / 1.25
event.final_damage_amount = event.final_damage_amount / 1.25
elseif event.damage_type.name and (event.damage_type.name == 'explosion') then
adjusted_damage = adjusted_damage / 1.5
event.final_damage_amount = event.final_damage_amount / 1.5
elseif event.damage_type.name and (event.damage_type.name == 'fire') then
adjusted_damage = adjusted_damage / 1.25
event.final_damage_amount = event.final_damage_amount / 1.25
end
-- and additionally:
if event.cause and event.cause.valid and event.cause.name == 'artillery-turret' then
adjusted_damage = adjusted_damage / 1.5
event.final_damage_amount = event.final_damage_amount / 1.5
end
if event.damage_type.name and (event.damage_type.name == 'laser') then
adjusted_damage = adjusted_damage / 7 --laser turrets are in range. give some resistance
event.final_damage_amount = event.final_damage_amount / 7 --laser turrets are in range. give some resistance
end
-- There should be a better way to do it than this...
if memory.healthbars and memory.healthbars[unit_number] then
local kraken_id = memory.healthbars[unit_number].id
local remaining_health = Common.entity_damage_healthbar(event.entity, adjusted_damage)
local remaining_health = Common.entity_damage_healthbar(event.entity, event.final_damage_amount)
if remaining_health and remaining_health <= 0 then
Kraken.kraken_die(kraken_id)
end
@ -451,7 +454,6 @@ local function other_enemy_damage_bonuses(event)
end
-- @TODO: Fix elite biters getting one shotted by Samurai/Hatamoto classes (it doesn't play well with virtual health) as well as check for other inconsistencies/issues when damaging entities with virtual health
local function damage_dealt_by_players_changes(event)
local memory = Memory.get_crew_memory()
@ -473,8 +475,38 @@ local function damage_dealt_by_players_changes(event)
-- 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 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 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
Common.damage_hostile_entity(event.entity, (Balance.quartermaster_bonus_physical_damage - 1) * event.final_damage_amount)
event.final_damage_amount = event.final_damage_amount * Balance.quartermaster_bonus_physical_damage
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((Balance.pistol_damage_multiplier() - 1) * event.final_damage_amount, character.force, 'impact', character) --triggers this function again, but not physical this time
Common.damage_hostile_entity(event.entity, (Balance.pistol_damage_multiplier() - 1) * event.final_damage_amount)
event.final_damage_amount = event.final_damage_amount * Balance.pistol_damage_multiplier()
end
end
end
if class and class == Classes.enum.SCOUT then
event.entity.health = event.entity.health + (1 - Balance.scout_damage_dealt_multiplier) * event.final_damage_amount
-- event.entity.health = event.entity.health + (1 - Balance.scout_damage_dealt_multiplier) * event.final_damage_amount
Common.damage_hostile_entity(event.entity, -(1 - Balance.scout_damage_dealt_multiplier) * event.final_damage_amount)
event.final_damage_amount = event.final_damage_amount * Balance.scout_damage_dealt_multiplier
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
@ -496,20 +528,28 @@ local function damage_dealt_by_players_changes(event)
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.
elseif acid then --this hacky stuff is to implement repeated spillover splash damage, whilst getting around the fact that if overkill 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
else
if samurai then
event.entity.health = event.entity.health + (1 - Balance.samurai_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
-- event.entity.health = event.entity.health + (1 - Balance.samurai_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
Common.damage_hostile_entity(event.entity, -(1 - Balance.samurai_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount)
event.final_damage_amount = event.final_damage_amount * Balance.samurai_damage_dealt_when_not_melee_multiplier
elseif hatamoto then
event.entity.health = event.entity.health + (1 - Balance.hatamoto_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
-- event.entity.health = event.entity.health + (1 - Balance.hatamoto_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
Common.damage_hostile_entity(event.entity, -(1 - Balance.hatamoto_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount)
event.final_damage_amount = event.final_damage_amount * Balance.hatamoto_damage_dealt_when_not_melee_multiplier
end
end
-- @TODO: This should preferably be reworked, so that "event_on_entity_damaged()" could be simpler by just returning multiplier, although doing AoE is quite fun.
-- @TODO: "event.entity.health >= extra_damage_to_deal" is pointless when enemy has virtual healthbar
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
-- 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
Common.damage_hostile_entity(event.entity, extra_damage_to_deal)
event.final_damage_amount = event.final_damage_amount + extra_damage_to_deal
else
local surplus = (extra_damage_to_deal - event.entity.health)*0.8
event.entity.die(character.force, character)
@ -520,30 +560,6 @@ local function damage_dealt_by_players_changes(event)
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
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
end
@ -564,8 +580,8 @@ local function swamp_resist_poison(event)
if not ((entity.type and entity.type == 'tree') or (event.entity.force and event.entity.force.name == memory.enemy_force_name)) then return end
local damage = event.final_damage_amount
event.entity.health = event.entity.health + damage
event.entity.health = event.entity.health + event.final_damage_amount
event.final_damage_amount = 0
end
@ -582,18 +598,20 @@ local function maze_walls_resistance(event)
if not ((entity.type and entity.type == 'tree') or entity.name == 'rock-huge' or entity.name == 'rock-big' or entity.name == 'sand-rock-big') then return end
local damage = event.final_damage_amount
if (event.damage_type.name and (event.damage_type.name == 'explosion' or event.damage_type.name == 'poison')) then
event.entity.health = event.entity.health + damage
event.entity.health = event.entity.health + event.final_damage_amount
event.final_damage_amount = 0
elseif event.damage_type.name and event.damage_type.name == 'fire' then
-- put out forest fires:
for _, e2 in pairs(entity.surface.find_entities_filtered({area = {{entity.position.x - 4, entity.position.y - 4},{entity.position.x + 4, entity.position.y + 4}}, name = "fire-flame-on-tree"})) do
if e2.valid then e2.destroy() end
end
else
if string.sub(event.cause.force.name, 1, 4) == 'crew' then --player damage only
event.entity.health = event.entity.health + damage * 0.9
if event.cause and event.cause.valid then
if string.sub(event.cause.force.name, 1, 4) == 'crew' then --player damage only
event.entity.health = event.entity.health + event.final_damage_amount * 0.9
event.final_damage_amount = event.final_damage_amount * 0.1
end
end
end
end
@ -627,6 +645,9 @@ end
-- -- end
-- end
-- Piratux: I feel sorry for whoever needs to lay eyes on this. Bottle of bleach is adviced to have by your side.
-- @TODO: Possible rework solution: "event_on_entity_damaged()" should accumulate final damage dealt multiplier, and "fix" entity health or deal proper damage to virtual healthbar at the very end of the function. Entity deaths should be handled at "event_on_entity_died()" instead, to avoid the mess.
-- NOTE: "event.cause" may not always be provided.
-- However, special care needs to be taken when "event.cause" is nil and entity has healthbar (better not ignore such damage or it can cause issues, such as needing to handle their death on "entity_died" functions as opposed to here)
local function event_on_entity_damaged(event)
@ -1314,13 +1335,48 @@ local function event_on_entity_died(event)
-- I think the only reason krakens don't trigger this right now is that they are destroyed rather than .die()
else
local destination = Common.current_destination()
if not (destination and destination.dynamic_data and destination.dynamic_data.quest_type and (not destination.dynamic_data.quest_complete)) then return end
if destination.dynamic_data.quest_type == Quest.enum.WORMS and entity.type == 'turret' then
destination.dynamic_data.quest_progress = destination.dynamic_data.quest_progress + 1
Quest.try_resolve_quest()
if destination and destination.dynamic_data and destination.dynamic_data.quest_type and (not destination.dynamic_data.quest_complete) then
if destination.dynamic_data.quest_type == Quest.enum.WORMS and entity.type == 'turret' then
destination.dynamic_data.quest_progress = destination.dynamic_data.quest_progress + 1
Quest.try_resolve_quest()
end
end
end
end
-- elite biter death
local elite_biters = memory.elite_biters
if elite_biters and entity and entity.valid and entity.force.name == memory.enemy_force_name and elite_biters and elite_biters[entity.unit_number] then
local surface = entity.surface
if surface and surface.valid then
-- Shoot spit around and spawn biters where spit lands
local arc_size = (2 * Math.pi) / Balance.biters_spawned_on_elite_biter_death
for i = 1, Balance.biters_spawned_on_elite_biter_death, 1 do
local offset = Math.random_vec_in_arc(Math.random(4, 8), arc_size * i, arc_size)
local target_pos = Math.vector_sum(entity.position, offset)
local stream = surface.create_entity{
name = 'acid-stream-spitter-big',
position = entity.position,
force = memory.enemy_force_name,
source = entity.position,
target = target_pos,
max_range = 500,
speed = 0.1
}
if not memory.elite_biters_stream_registrations then memory.elite_biters_stream_registrations = {} end
memory.elite_biters_stream_registrations[#memory.elite_biters_stream_registrations + 1] = {
number = script.register_on_entity_destroyed(stream),
position = target_pos,
biter_name = entity.name,
surface_name = surface.name -- surface name is needed to know where biter died
}
end
end
memory.elite_biters[entity.unit_number] = nil
end
end
function Public.research_apply_buffs(event)
@ -1435,22 +1491,26 @@ local function event_on_player_joined_game(event)
local crew_to_put_back_in = nil
for _, memory in pairs(global_memory.crew_memories) do
if Common.is_id_valid(memory.id) and memory.crewstatus == Crew.enum.ADVENTURING and memory.temporarily_logged_off_characters[player.index] then
if Common.is_id_valid(memory.id) and memory.crewstatus == Crew.enum.ADVENTURING and memory.temporarily_logged_off_player_data[player.index] then
crew_to_put_back_in = memory.id
break
end
end
if crew_to_put_back_in then
Crew.join_crew(player, crew_to_put_back_in, true)
log('INFO: ' .. player.name .. ' (crew ID: ' .. crew_to_put_back_in .. ') joined the game')
local memory = global_memory.crew_memories[crew_to_put_back_in]
Memory.set_working_id(crew_to_put_back_in)
Crew.join_crew(player, true)
local memory = Memory.get_crew_memory()
if (not memory.run_is_protected) and #memory.crewplayerindices <= 1 then
Roles.make_captain(player)
end
if _DEBUG then log('putting player back in their old crew') end
else
log('INFO: ' .. player.name .. ' (crew ID: NONE) joined the game')
if player.character and player.character.valid then
player.character.destroy()
end
@ -1473,6 +1533,8 @@ local function event_on_player_joined_game(event)
Common.notify_player_expected(player, {'pirates.player_join_game_info'})
player.force = Common.lobby_force_name
-- It was suggested to always spawn players in lobby, in hopes that they may want to create their crew increasing the popularity of scenario.
-- Auto-join the oldest crew:
@ -1503,7 +1565,7 @@ local function event_on_player_joined_game(event)
-- end
-- )
-- if ages[1] then
-- Crew.join_crew(player, ages[1].id)
-- Crew.join_crew(player)
-- local memory = global_memory.crew_memories[ages[1].id]
-- if (not memory.run_is_protected) and #memory.crewplayerindices <= 1 then
@ -1563,6 +1625,11 @@ local function event_on_pre_player_left_game(event)
local global_memory = Memory.get_global_memory()
-- figure out which crew this is about:
local crew_id = Common.get_id_from_force_name(player.force.name)
if crew_id then
log('INFO: ' .. player.name .. ' (crew ID: ' .. crew_id .. ') left the game')
else
log('INFO: ' .. player.name .. ' (crew ID: NONE) left the game')
end
for k, proposal in pairs(global_memory.crewproposals) do
if proposal and proposal.endorserindices then
@ -2080,7 +2147,7 @@ local function event_on_console_chat(event)
local memory = Memory.get_crew_memory()
-- NOTE: This check to see if player is in a crew is not reliable and can sometimes cause errors!
if player.force.name == 'player' then
if player.force.name == Common.lobby_force_name then
local other_force_indices = global_memory.crew_active_ids
for _, index in pairs(other_force_indices) do

View File

@ -262,33 +262,35 @@ function Public.prune_offline_characters_list(tickinterval)
if memory.game_lost then return end
for player_index, tick in pairs(memory.temporarily_logged_off_characters) do
if player_index and game.players[player_index] and game.players[player_index].connected then
memory.temporarily_logged_off_characters[player_index] = nil
if memory.temporarily_logged_off_characters_items[player_index] then
memory.temporarily_logged_off_characters_items[player_index].destroy()
end
memory.temporarily_logged_off_characters_items[player_index] = nil
for player_index, data in pairs(memory.temporarily_logged_off_player_data) do
if game.players[player_index] and game.players[player_index].connected then
-- memory.temporarily_logged_off_characters[player_index] = nil
-- if memory.temporarily_logged_off_characters_items[player_index] then
-- memory.temporarily_logged_off_characters_items[player_index].destroy()
-- end
-- memory.temporarily_logged_off_characters_items[player_index] = nil
memory.temporarily_logged_off_player_data[player_index] = nil
else
if player_index and tick < game.tick - 60 * 60 * Common.logged_off_items_preserved_minutes then
local any = false
local temp_inv = memory.temporarily_logged_off_characters_items[player_index]
if temp_inv then
for i = 1, #temp_inv, 1 do
if temp_inv[i] and temp_inv[i].valid and temp_inv[i].valid_for_read then
Common.give_items_to_crew(temp_inv[i])
any = true
end
end
if any then
Common.notify_force_light(memory.force, {'pirates.recover_offline_player_items'})
end
local tick = data.tick
if tick < game.tick - 60 * 60 * Common.temporarily_logged_off_player_data_preservation_minutes then
-- local any = false
-- local temp_inv = memory.temporarily_logged_off_characters_items[player_index]
-- if temp_inv then
-- for i = 1, #temp_inv, 1 do
-- if temp_inv[i] and temp_inv[i].valid and temp_inv[i].valid_for_read then
-- Common.give_items_to_crew(temp_inv[i])
-- any = true
-- end
-- end
temp_inv.destroy()
end
-- if any then
-- Common.notify_force_light(memory.force, {'pirates.recover_offline_player_items'})
-- end
memory.temporarily_logged_off_characters[player_index] = nil
memory.temporarily_logged_off_characters_items[player_index] = nil
-- temp_inv.destroy()
-- end
memory.temporarily_logged_off_player_data[player_index] = nil
end
end
end
@ -1706,19 +1708,14 @@ function Public.update_time_remaining()
if memory.boat.state == Boats.enum_state.RETREATING then return end
if not memory.boat.surface_name then return end
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
if destination.static_params and destination.static_params.base_cost_to_undock and Balance.need_resources_to_undock(Common.overworldx()) == true and (not Common.query_can_pay_cost_to_leave()) then
if destination.type == Surfaces.enum.ISLAND then
if destination.static_params and destination.static_params.base_cost_to_undock and Boats.need_resources_to_undock(Common.overworldx(), destination.subtype) and (not Common.query_can_pay_cost_to_leave()) then
Crew.try_lose({'pirates.loss_resources_were_not_collected_in_time'})
else
if Balance.need_resources_to_undock(Common.overworldx()) == true then
Progression.try_retreat_from_island(false)
else
Progression.retreat_from_island(false)
end
Common.consume_undock_cost_resources()
Progression.retreat_from_island(false)
end
elseif type == Surfaces.enum.DOCK then
elseif destination.type == Surfaces.enum.DOCK then
Progression.undock_from_dock(false)
end
end

View File

@ -37,12 +37,12 @@ Public.class_reward_tick_rate_in_seconds = 7
Public.poison_damage_multiplier = 1.85
Public.every_nth_tree_gives_coins = 10
Public.samurai_damage_taken_multiplier = 0.32
Public.samurai_damage_taken_multiplier = 0.45
Public.samurai_damage_dealt_when_not_melee_multiplier = 0.75
Public.samurai_damage_dealt_with_melee = 25
Public.hatamoto_damage_taken_multiplier = 0.21
Public.samurai_damage_dealt_with_melee = 30
Public.hatamoto_damage_taken_multiplier = 0.3
Public.hatamoto_damage_dealt_when_not_melee_multiplier = 0.75
Public.hatamoto_damage_dealt_with_melee = 45
Public.hatamoto_damage_dealt_with_melee = 50
Public.iron_leg_damage_taken_multiplier = 0.24
Public.iron_leg_iron_ore_required = 3000
Public.deckhand_extra_speed = 1.25
@ -93,6 +93,10 @@ Public.min_ore_spawn_distance = 10
Public.biter_boats_start_arrive_x = 40 * 5
Public.need_resources_to_undock_x = 40 * 20
Public.biters_spawned_on_elite_biter_death = 4
Public.walkways_frozen_pool_damage = 12
function Public.starting_boatEEIpower_production_MW()
-- return 3 * Math.sloped(Common.capacity_scale(), 1/2) / 2 --/2 as we have 2
return 3/2
@ -167,7 +171,8 @@ function Public.game_slowness_scale()
-- return 1 / Public.crew_scale()^(55/100) / Math.sloped(Common.difficulty_scale(), 1/4) --changed crew_scale factor significantly to help smaller crews
-- return 1 / (Public.crew_scale()^(50/100) / Math.sloped(Common.difficulty_scale(), 1/4)) --changed crew_scale factor significantly to help smaller crews
local scale = 0.3 + Math.sloped(Common.difficulty_scale(), -0.15) / (Public.crew_scale()^(1/8))
-- local scale = 0.3 + Math.sloped(Common.difficulty_scale(), -0.15) / (Public.crew_scale()^(1/8))
local scale = 2.6 * Math.sloped(Common.difficulty_scale(), -0.2) - Public.crew_scale()^(1/4)
return Math.max(1, scale)
end
@ -179,20 +184,10 @@ function Public.max_time_on_island_formula() --always >0 --tuned
-- (33 + 0.2 * (Common.overworldx()/40)^(1/3)) --based on observing x=2000, lets try killing the extra time
-- ) * Public.game_slowness_scale()
local minimum_mins_on_island = 40
local minimum_mins_on_island = 30
return Math.ceil(60 * minimum_mins_on_island * Public.game_slowness_scale())
end
-- Returns true if uncollected resources will cause the crew to lose.
function Public.need_resources_to_undock(overworldx)
if overworldx >= Public.need_resources_to_undock_x then
return true
else
return false
end
end
-- In seconds
function Public.max_time_on_island(island_subtype)
local x = Common.overworldx()
@ -518,6 +513,9 @@ Public.starting_fuel = 4000
Public.silo_max_hp = 5000
Public.silo_resistance_factor = 7
-- Pistol shooting speed = 4/s
-- Submachine gun shooting speed = 10/s
-- Pistol damage multiplier shouldn't be >= 2.5, otherwise Submachine gun isn't worth using.
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_static_evo = 0.35
@ -579,7 +577,7 @@ function Public.krakens_per_free_slot(overworldx)
if rng < 0.0025 * multiplier then
return 3
elseif rng < 0.075 * multiplier then
return 1
return 2
elseif rng < 0.5 * multiplier then
return 1
else

View File

@ -36,6 +36,8 @@ local Classes = require 'maps.pirates.roles.classes'
local Gui = require 'maps.pirates.gui.gui'
-- local Session = require 'utils.datastore.session_data'
local function cmd_set_memory(cmd)
@ -46,7 +48,6 @@ 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
@ -415,6 +416,7 @@ function(cmd)
end
end)
-- Try undock from an island or dock
commands.add_command(
'undock',
{'pirates.cmd_explain_undock'},
@ -435,6 +437,27 @@ function(cmd)
end
end)
-- Force undock from an island or dock
commands.add_command(
'ret',
{'pirates.cmd_explain_dev'},
function(cmd)
cmd_set_memory(cmd)
local memory = Memory.get_crew_memory()
if not Common.is_id_valid(memory.id) then return end
-- local param = tostring(cmd.parameter)
if check_admin(cmd) then
if memory.boat.state == Boats.enum_state.DOCKED then
Progression.undock_from_dock(true)
elseif memory.boat.state == Boats.enum_state.LANDED then
Progression.retreat_from_island(true)
end
end
end)
commands.add_command(
'tax',
{'pirates.cmd_explain_tax'},
@ -530,20 +553,6 @@ function(cmd)
end
end)
-- Undock from an island or dock
commands.add_command(
'ret',
{'pirates.cmd_explain_dev'},
function(cmd)
cmd_set_memory(cmd)
local param = tostring(cmd.parameter)
if check_admin(cmd) then
local player = game.players[cmd.player_index]
Progression.retreat_from_island(true)
end
end)
-- Move overworld boat right by a lot (you can jump over islands that way to skip them)
commands.add_command(
'jump',

View File

@ -63,9 +63,11 @@ Public.ban_from_rejoining_crew_ticks = 45 * 60 --to prevent observing map and re
Public.afk_time = 60 * 60 * 5
Public.afk_warning_time = 60 * 60 * 4.5
Public.logged_off_items_preserved_minutes = 5
Public.temporarily_logged_off_player_data_preservation_minutes = 1
Public.logout_unprotected_items = {'uranium-235', 'uranium-238', 'fluid-wagon', 'coal', 'electric-engine-unit', 'flying-robot-frame', 'advanced-circuit', 'beacon', 'speed-module-3', 'speed-module-2', 'roboport', 'construction-robot'} --internal inventories of these will not be preserved
Public.lobby_force_name = 'player'
-- Public.mainshop_rate_limit_ticks = 11
@ -138,7 +140,7 @@ end
function Public.notify_lobby(message, color_override)
color_override = color_override or CoreData.colors.notify_lobby
game.forces['player'].print({"", '>> ', message}, color_override)
game.forces[Public.lobby_force_name].print({"", '>> ', message}, color_override)
end
function Public.notify_force(force, message, color_override)
@ -688,6 +690,16 @@ function Public.spend_stored_resources(to_spend)
Public.update_boat_stored_resources()
end
function Public.consume_undock_cost_resources()
local destination = Public.current_destination()
local cost = destination.static_params.base_cost_to_undock
if cost then
local adjusted_cost = Public.time_adjusted_departure_cost(cost)
Public.spend_stored_resources(adjusted_cost)
end
end
function Public.new_healthbar(text, target_entity, max_health, optional_id, health, size, extra_offset, location_override)
health = health or max_health
@ -773,11 +785,11 @@ end
function Public.entity_damage_healthbar(entity, damage, location_override)
location_override = location_override or Memory.get_crew_memory()
if not (location_override.healthbars) then return end
if not (location_override.healthbars) then return nil end
local unit_number = entity.unit_number
local healthbar = location_override.healthbars[unit_number]
if not healthbar then return end
if not healthbar then return nil end
local new_health = healthbar.health - damage
healthbar.health = new_health
@ -787,11 +799,17 @@ function Public.entity_damage_healthbar(entity, damage, location_override)
entity.health = entity.prototype.max_health
end
if healthbar.health > healthbar.max_health then
healthbar.health = healthbar.max_health
end
local final_health = healthbar.health
if healthbar.health <= 0 then
location_override.healthbars[unit_number] = nil
end
return healthbar.health
return final_health
end
function Public.update_healthbar_rendering(new_healthbar, health)
@ -1849,7 +1867,7 @@ function Public.try_make_biter_elite(entity)
local memory = Memory.get_crew_memory()
local difficulty_index = CoreData.get_difficulty_option_from_value(memory.difficulty)
if difficulty_index < 3 then return end
if difficulty_index < 3 and Public.overworldx() < 800 then return end
if Public.overworldx() == 0 then return end
@ -1858,7 +1876,7 @@ function Public.try_make_biter_elite(entity)
local health_multiplier
if difficulty_index == 3 then
if difficulty_index <= 3 then
health_multiplier = 5
else
health_multiplier = 10
@ -1881,4 +1899,26 @@ function Public.try_make_biter_elite(entity)
end
end
-- This function is meant to handle damage adjustment cases that automatically damages/heals either entity or its virtual health.
-- NOTE: This is only meant for hostile entities (for now at least), as friendly units with healthbars are more difficult to handle
-- NOTE: "damage" can also be negative, which will heal the entity (but not past maximum health)
function Public.damage_hostile_entity(entity, damage)
if not (entity and entity.valid) then return end
local remaining_health = Public.entity_damage_healthbar(entity, damage)
-- Does entity have virtual healthbar
if remaining_health then
if remaining_health <= 0 then
entity.die()
end
else -- Not, so treat it as simple entity
-- Note: According to docs, health is automatically clamped to [0, max_health] so we don't need to do it
entity.health = entity.health - damage
if entity.health <= 0 then
entity.die()
end
end
end
return Public

View File

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

View File

@ -95,6 +95,8 @@ function Public.update_difficulty()
memory.difficulty_option = modal_id
memory.difficulty = CoreData.difficulty_options[modal_id].value
Cabin.update_captains_market_offers_based_on_difficulty(memory.difficulty_option)
end
end
@ -266,7 +268,7 @@ function Public.join_spectators(player, crewid)
player.set_controller{type = defines.controllers.spectator}
end
local c = surface.create_entity{name = 'character', position = surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, force = 'player'}
local c = surface.create_entity{name = 'character', position = surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, force = Common.lobby_force_name}
player.associate_character(c)
@ -331,14 +333,11 @@ function Public.leave_spectators(player, quiet)
if _DEBUG then memory.crew_disband_tick = game.tick + 30*60*60 end
end
player.force = 'player'
player.force = Common.lobby_force_name
end
function Public.join_crew(player, crewid, rejoin)
if not crewid then return end
Memory.set_working_id(crewid)
function Public.join_crew(player, rejoin)
local memory = Memory.get_crew_memory()
if not Common.validate_player(player) then return end
@ -367,7 +366,7 @@ function Public.join_crew(player, crewid, rejoin)
if spectating then
local chars = player.get_associated_characters()
for _, char in pairs(chars) do
char.destroy()
char.destroy()
end
player.teleport(surface.find_non_colliding_position('character', memory.spawnpoint, 32, 0.5) or memory.spawnpoint, surface)
@ -377,22 +376,51 @@ function Public.join_crew(player, crewid, rejoin)
memory.spectatorplayerindices = Utils.ordered_table_with_values_removed(memory.spectatorplayerindices, player.index)
else
if not (player.character and player.character.valid) then
player.set_controller{type = defines.controllers.god}
player.create_character()
end
Public.player_abandon_endorsements(player)
player.force = memory.force
player.teleport(surface.find_non_colliding_position('character', memory.spawnpoint, 32, 0.5) or memory.spawnpoint, surface)
Common.notify_lobby({'pirates.lobby_to_crew_2', player.name, memory.name})
end
Common.give_back_items_to_temporarily_logged_off_player(player)
player.teleport(surface.find_non_colliding_position('character', memory.spawnpoint, 32, 0.5) or memory.spawnpoint, surface)
if rejoin then
if memory.temporarily_logged_off_player_data[player.index] then
local rejoin_data = memory.temporarily_logged_off_player_data[player.index]
local rejoin_surface = game.surfaces[rejoin_data.surface_name]
-- If surface where player left the game still exists, place him there.
if rejoin_surface and rejoin_surface.valid then
-- Edge case: if player left the game while he was on the boat, it could be that boat position
-- changed when he left the game vs when he came back.
if not (rejoin_data.on_boat and rejoin_data.on_island) then
player.teleport(rejoin_surface.find_non_colliding_position('character', rejoin_data.position, 32, 0.5) or memory.spawnpoint, rejoin_surface)
end
end
-- We shouldn't give back items when player was on island, but that island is gone.
-- Left in case we decide to store player inventory in offline character instead of in the corpse.
-- if not (rejoin_data.on_island and (not (rejoin_surface and rejoin_surface.valid))) then
-- Common.give_back_items_to_temporarily_logged_off_player(player)
-- end
memory.temporarily_logged_off_player_data[player.index] = nil
end
end
end
Common.notify_force(player.force, {'pirates.lobby_to_crew', player.name})
-- Server.to_discord_embed_raw(CoreData.comfy_emojis.yum1 .. '[' .. memory.name .. '] ' .. message)
memory.crewplayerindices[#memory.crewplayerindices + 1] = player.index
-- don't give them items if they've been in the crew recently:
if not (memory.tempbanned_from_joining_data and memory.tempbanned_from_joining_data[player.index]) and (not rejoin) then --just using tempbanned_from_joining_data as a quick proxy for whether the player has ever been in this run before
-- don't give them items if they've been in the crew recently
-- just using tempbanned_from_joining_data as a quick proxy for whether the player has ever been in this run before
if not (memory.tempbanned_from_joining_data and memory.tempbanned_from_joining_data[player.index]) and (not rejoin) then
for item, amount in pairs(Balance.starting_items_player_late) do
player.insert({name = item, count = amount})
end
@ -436,33 +464,48 @@ function Public.leave_crew(player, to_lobby, quiet)
-- -- Server.to_discord_embed_raw(CoreData.comfy_emojis.feel .. '[' .. memory.name .. '] ' .. message)
-- end
local player_surface_type = SurfacesCommon.decode_surface_name(player.surface.name).type
local boat_surface_type = SurfacesCommon.decode_surface_name(memory.boat.surface_name).type
-- @TODO: figure out why surface_name can be nil
-- When player remains in island when ship leaves, prevent him from getting items back
local save_items = true
if player.surface and
player.surface.valid and
memory.boat and
memory.boat.surface_name
then
local player_surface_type = SurfacesCommon.decode_surface_name(player.surface.name).type
local boat_surface_type = SurfacesCommon.decode_surface_name(memory.boat.surface_name).type
-- local save_items = true
-- if player.surface and
-- player.surface.valid and
-- memory.boat and
-- memory.boat.surface_name
-- then
-- if player_surface_type == Surfaces.enum.ISLAND and boat_surface_type == Surfaces.enum.SEA then
-- save_items = false
-- end
-- end
if player_surface_type == Surfaces.enum.ISLAND and boat_surface_type == Surfaces.enum.SEA then
save_items = false
end
-- Code regarding item saving is left here if we decide it's better to store items in
-- logged off character as opposed to in the character corpse.
-- if to_lobby then
-- if save_items then
-- Common.send_important_items_from_player_to_crew(player, true)
-- end
-- char.die(memory.force_name)
-- else
if not to_lobby then
if not memory.temporarily_logged_off_player_data then memory.temporarily_logged_off_player_data = {} end
memory.temporarily_logged_off_player_data[player.index] = {
on_island = (player_surface_type == Surfaces.enum.ISLAND),
on_boat = (player_surface_type == boat_surface_type) and Boats.on_boat(memory.boat, player.character.position),
surface_name = player.surface.name,
position = player.character.position,
tick = game.tick
}
-- if save_items then
-- Common.temporarily_store_logged_off_character_items(player)
-- end
-- memory.temporarily_logged_off_characters[player.index] = game.tick
end
if to_lobby then
if save_items then
Common.send_important_items_from_player_to_crew(player, true)
end
char.die(memory.force_name)
else
if save_items then
Common.temporarily_store_logged_off_character_items(player)
end
memory.temporarily_logged_off_characters[player.index] = game.tick
end
char.die(memory.force_name)
-- else
-- if not quiet then
@ -475,7 +518,7 @@ function Public.leave_crew(player, to_lobby, quiet)
player.set_controller{type = defines.controllers.god}
player.teleport(surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, surface)
player.force = 'player'
player.force = Common.lobby_force_name
player.create_character()
Event.raise(BottomFrame.events.bottom_quickbar_respawn_raise, {player_index = player.index})
end
@ -554,7 +597,7 @@ function Public.disband_crew(donotprint)
for _,player in pairs(players) do
if player.controller_type == defines.controllers.editor then player.toggle_map_editor() end
player.force = 'player'
player.force = Common.lobby_force_name
end
if (not donotprint) then
@ -740,12 +783,14 @@ function Public.initialise_crew(accepted_proposal)
memory.spectatorplayerindices = {}
memory.tempbanned_from_joining_data = {}
memory.destinations = {}
memory.temporarily_logged_off_characters = {}
memory.temporarily_logged_off_characters_items = {}
-- memory.temporarily_logged_off_characters = {}
-- memory.temporarily_logged_off_characters_items = {}
memory.temporarily_logged_off_player_data = {}
memory.class_renderings = {}
memory.class_auxiliary_data = {}
memory.elite_biters = {}
memory.elite_biters_stream_registrations = {}
memory.pet_biters = {}
memory.hold_surface_count = 1
@ -786,8 +831,8 @@ function Public.initialise_crew(accepted_proposal)
memory.officers_table = {}
memory.classes_table = {} -- stores all unlocked untaken classes
memory.spare_classes = {} -- stores all unlocked taken classes
memory.classes_table = {} -- stores all unlocked taken classes
memory.spare_classes = {} -- stores all unlocked untaken classes
memory.recently_purchased_classes = {} -- stores recently unlocked classes to add it back to available class pool list later
memory.unlocked_classes = {} -- stores all unlocked classes just for GUI (to have consistent order)
memory.available_classes_pool = Classes.initial_class_pool() -- stores classes that can be randomly picked for unlocking
@ -875,8 +920,8 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.set_friend('player', true)
game.forces['player'].set_friend(crew_force, true)
crew_force.set_friend(Common.lobby_force_name, true)
game.forces[Common.lobby_force_name].set_friend(crew_force, true)
crew_force.set_friend(ancient_friendly_force, true)
ancient_friendly_force.set_friend(crew_force, true)
enemy_force.set_friend(ancient_friendly_force, true)
@ -915,9 +960,9 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.set_turret_attack_modifier(k, v)
end
crew_force.technologies['kovarex-enrichment-process'].researched = true -- needed for radioactive island
-- crew_force.technologies['circuit-network'].researched = true
-- crew_force.technologies['uranium-processing'].researched = true
-- crew_force.technologies['kovarex-enrichment-process'].researched = true
-- crew_force.technologies['gun-turret'].researched = true
-- crew_force.technologies['electric-energy-distribution-1'].researched = true
-- crew_force.technologies['electric-energy-distribution-2'].researched = true
@ -953,7 +998,7 @@ function Public.reset_crew_and_enemy_force(id)
crew_force.technologies['artillery'].enabled = false
-- crew_force.technologies['destroyer'].enabled = false
crew_force.technologies['spidertron'].enabled = false
crew_force.technologies['atomic-bomb'].enabled = false
-- crew_force.technologies['atomic-bomb'].enabled = false -- experimenting
crew_force.technologies['explosive-rocketry'].enabled = false
-- crew_force.technologies['research-speed-1'].enabled = false

View File

@ -114,17 +114,18 @@ function Public.toggle_window(player)
flow3.style.font_color = {r = 0.10, g = 0.10, b = 0.10}
flow3.tooltip = {'pirates.gui_crew_window_buttons_quit_crew_tooltip'}
flow3 =
flow2.add(
{
name = 'leave_spectators',
type = 'button',
caption = {'pirates.gui_crew_window_buttons_quit_spectators'}
}
)
flow3.style.minimal_width = 95
flow3.style.font = 'default-bold'
flow3.style.font_color = {r = 0.10, g = 0.10, b = 0.10}
-- Runs window already has a button to leave spectators.
-- flow3 =
-- flow2.add(
-- {
-- name = 'crewmember_leave_spectators',
-- type = 'button',
-- caption = {'pirates.gui_crew_window_buttons_quit_spectators'}
-- }
-- )
-- 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(
@ -138,18 +139,19 @@ function Public.toggle_window(player)
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 = {'pirates.gui_crew_window_buttons_join_spectators'}
}
)
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 = {'pirates.gui_crew_window_buttons_join_spectators_tooltip'}
-- Disabled spectators for now... might not play well with maze world
-- flow3 =
-- flow2.add(
-- {
-- name = 'crewmember_join_spectators',
-- type = 'button',
-- caption = {'pirates.gui_crew_window_buttons_join_spectators'}
-- }
-- )
-- 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 = {'pirates.gui_crew_window_buttons_join_spectators_tooltip'}
--*** MEMBERS AND SPECTATORS ***--
@ -437,8 +439,7 @@ function Public.full_update(player)
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.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))
@ -501,18 +502,18 @@ function Public.click(event)
local memory = Memory.get_crew_memory()
if eventname == 'crewmember_join_spectators' then
Crew.join_spectators(player, memory.id)
return
end
-- 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 == 'crewmember_leave_spectators' then
-- Crew.leave_spectators(player)
-- return
-- end
if eventname == 'spectator_join_crew' then
Crew.join_crew(player, memory.id)
Crew.join_crew(player)
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.notify_player_expected(player, {'pirates.player_joins_protected_run_with_no_captain'})

View File

@ -619,7 +619,7 @@ function Public.process_etaframe_update(player, flow1, bools)
-- local caption
if bools.atsea_loading_bool then
flow2.etaframe_label_3.caption = {'pirates.gui_etaframe_next_escape_cost'}
if Balance.need_resources_to_undock(Common.overworldx()) then
if Boats.need_resources_to_undock(Common.overworldx(), destination.subtype) then
if bools.cost_includes_rocket_launch_bool then
tooltip = {'pirates.resources_needed_tooltip_4_rocketvariant'}
else
@ -649,7 +649,7 @@ function Public.process_etaframe_update(player, flow1, bools)
tooltip = {'pirates.resources_needed_tooltip_3'}
end
else -- Shown when at island
if Balance.need_resources_to_undock(Common.overworldx()) == true then
if Boats.need_resources_to_undock(Common.overworldx(), destination.subtype) then
flow2.etaframe_label_3.visible = false
if bools.cost_includes_rocket_launch_bool then
@ -1220,7 +1220,7 @@ end
-- ATTENTION: Giving same names to GUI elements can cause issues, because click events are dispatched to all GUI windows!
local function on_gui_click(event)
if not event then return end
if not event.element then return end

View File

@ -696,7 +696,11 @@ function Public.click(event)
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]))
-- It was observed that "listbox.get_item(listbox.selected_index)" can produce "Index out of range error"
-- This is to prevent that error.
if listbox.selected_index >= 1 and listbox.selected_index <= #listbox.items then
Crew.join_spectators(player, tonumber(listbox.get_item(listbox.selected_index)[2]))
end
return
end
@ -707,34 +711,40 @@ function Public.click(event)
if eventname == 'join_crew' then
local listbox = flow.ongoing_runs.body.ongoing_runs_listbox
local crewid = tonumber(listbox.get_item(listbox.selected_index)[2])
local memory = global_memory.crew_memories[crewid]
-- It was observed that "listbox.get_item(listbox.selected_index)" can produce "Index out of range error"
-- This is to prevent that error.
if listbox.selected_index >= 1 and listbox.selected_index <= #listbox.items then
local crewid = tonumber(listbox.get_item(listbox.selected_index)[2])
-- If run is private
if global_memory.crew_memories[crewid].run_is_private then
if global_memory.crew_memories[crewid].private_run_password == flow.ongoing_runs.body.password_namefield.text then
Crew.join_crew(player, crewid)
flow.ongoing_runs.body.join_private_crew_info.visible = false
flow.ongoing_runs.body.password_namefield.visible = false
Memory.set_working_id(crewid)
local memory = Memory.get_crew_memory()
-- If run is private
if memory.run_is_private then
if memory.private_run_password == flow.ongoing_runs.body.password_namefield.text then
Crew.join_crew(player)
flow.ongoing_runs.body.join_private_crew_info.visible = false
flow.ongoing_runs.body.password_namefield.visible = false
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.notify_player_expected(player, {'pirates.player_joins_protected_run_with_no_captain'})
Common.notify_player_expected(player, {'pirates.create_new_crew_tip'})
end
else
Common.notify_player_error(player, {'pirates.gui_join_private_run_error_wrong_password'})
end
else
Crew.join_crew(player)
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.notify_player_expected(player, {'pirates.player_joins_protected_run_with_no_captain'})
Common.notify_player_expected(player, {'pirates.create_new_crew_tip'})
end
else
Common.notify_player_error(player, {'pirates.gui_join_private_run_error_wrong_password'})
end
else
Crew.join_crew(player, crewid)
if memory.run_is_protected and (not Roles.captain_exists()) then
Common.notify_player_expected(player, {'pirates.player_joins_protected_run_with_no_captain'})
Common.notify_player_expected(player, {'pirates.create_new_crew_tip'})
end
return
end
return
end
if eventname == 'propose_crew' then

View File

@ -45,7 +45,7 @@ Public.buried_treasure_loot_data_raw = {
Public.chest_loot_data_raw = {
{80, 0, 1, false, 'coin', 400, 700},
{30, 0, 1, false, 'rail-signal', 50, 50},
{10, 0, 1, false, 'rail-signal', 50, 50},
{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},
@ -412,7 +412,7 @@ Public.maze_treasure_data_raw = {
{2, 0, 1, false, 'uranium-rounds-magazine', 15, 25},
{2, 0, 1, false, 'artillery-shell', 5, 7},
{2, 0, 1, false, 'rail-signal', 400, 400},
{2, 0, 1, false, 'rail-signal', 250, 250},
{2, 0, 1, false, 'electric-engine-unit', 3, 4},
{2, 0, 1, false, 'cluster-grenade', 8, 12},

View File

@ -71,7 +71,7 @@ local Server = require 'utils.server'
local Math = require 'maps.pirates.math'
require 'utils.profiler'
-- require 'utils.profiler'
local Public = {}

View File

@ -100,16 +100,64 @@ function Public.random_float_in_range(from, to)
end
-- Returns vector in random direction.
-- scalar: sets returned vector length. If nil, 1 will be chosen
-- scalar: returned vector length. If nil, 1 will be chosen.
function Public.random_vec(scalar)
scalar = scalar or 1
local random_angle = Public.random_float_in_range(0, 2 * Public.pi)
return {
x = Public.sin(random_angle) * scalar,
y = Public.cos(random_angle) * scalar
x = Public.cos(random_angle) * scalar,
y = Public.sin(random_angle) * scalar
}
end
-- Returns vector in random direction in arc: [arc_offset, arc_offset + arc_size], starting at {x=1, y=1} and going anti-clockwise.
-- scalar: returned vector length. If nil, 1 will be chosen.
-- arc_offset: offset of arc in radians.
-- arc_size: size of arc in radians. Result is undefined with negative arc_size
function Public.random_vec_in_arc(scalar, arc_offset, arc_size)
scalar = scalar or 1
local random_angle = Public.random_float_in_range(arc_offset, arc_offset + arc_size)
return {
x = Public.cos(random_angle) * scalar,
y = Public.sin(random_angle) * scalar
}
end
-- Returns unique contiguous array indices.
-- array_size: size of contiguous array.
-- count: amount of unique indices to take from the array (elements are taken in range [1, array_size]).
--
-- Example with {array_size = 5, count = 3}:
-- - Possible return value: {4, 1, 5}
--
-- Idea taken from this big brained stranger https://stackoverflow.com/a/2380705
function Public.random_unique_array_indices(array_size, count)
if count > array_size then
return nil
end
local modified_indices = {}
local result_indices = {}
for i = 0, count - 1 do
local curr_array_size = array_size - i
local num = Public.random(curr_array_size)
if modified_indices[num] == nil then
result_indices[#result_indices + 1] = num
else
result_indices[#result_indices + 1] = modified_indices[num]
end
if modified_indices[curr_array_size] == nil then
modified_indices[num] = curr_array_size
else
modified_indices[num] = modified_indices[curr_array_size]
end
end
return result_indices
end
function Public.snap_to_grid(point)
return {x = Public.ceil(point.x), y = Public.ceil(point.x)}
end

View File

@ -86,8 +86,7 @@ function Public.initialise_crew_memory(id) --mostly serves as a dev reference of
memory.playerindex_captain = nil
memory.captain_accrued_time_data = nil
memory.max_players_recorded = nil
memory.temporarily_logged_off_characters = nil
memory.temporarily_logged_off_characters_items = nil
memory.temporarily_logged_off_player_data = nil
memory.speed_boost_characters = nil
@ -125,7 +124,7 @@ function Public.fallthrough_crew_memory() --could make this a metatable, but met
return {
id = 0,
difficulty = 1,
force_name = 'player',
force_name = 'player', -- should match Common.lobby_force_name
boat = {},
destinations = {},
spectatorplayerindices = {},

View File

@ -291,7 +291,7 @@ function Public.generate_overworld_destination(p)
static_params.base_cost_to_undock = Public.generate_destination_base_cost_to_undock(p, subtype) -- Multiplication by Balance.cost_to_leave_multiplier() happens later, in destination_on_collide.
static_params.undock_cost_decreases = true
if Balance.need_resources_to_undock(p.x) == true or subtype == IslandEnum.enum.RADIOACTIVE then
if Boats.need_resources_to_undock(p.x, subtype) then
static_params.undock_cost_decreases = false
end
@ -495,22 +495,15 @@ function Public.generate_overworld_destination(p)
-- 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
local random_indices = Math.random_unique_array_indices(#position_candidates, Math.min(kraken_count, 10))
if random_indices then
for _, idx in ipairs(random_indices) do
local p_chosen = position_candidates[idx]
local p_kraken = Utils.psum{p_chosen, p}
Crowsnest.draw_kraken(p_kraken)
memory.overworld_krakens[#memory.overworld_krakens + 1] = p_kraken
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
@ -577,16 +570,15 @@ 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
for i = #memory.overworld_krakens, 1, -1 do
local k = memory.overworld_krakens[i]
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)
memory.overworld_krakens = Utils.ordered_table_with_index_removed(memory.overworld_krakens, i)
end
end
end

View File

@ -475,13 +475,7 @@ function Public.try_retreat_from_island(player, manual) -- Assumes the cost can
Common.notify_player_error(player, {'pirates.error_undock_too_early'})
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
Common.consume_undock_cost_resources()
Public.retreat_from_island(manual)
end
else

View File

@ -1534,4 +1534,13 @@ function Public.force_reconnect_boat_poles()
end
end
-- Returns true if uncollected resources will cause the crew to lose.
function Public.need_resources_to_undock(overworldx, island_subtype)
if overworldx >= Balance.need_resources_to_undock_x or island_subtype == IslandEnum.enum.RADIOACTIVE then
return true
else
return false
end
end
return Public

View File

@ -393,8 +393,13 @@ function Public.tick_quest_structure_entry_price_check()
if removed > 0 then
local count = 1
for k, v in pairs(entry_price.batchRawMaterials) do
red_invs[count].insert({name = k, count = v * removed / entry_price.batchSize});
count = count + 1
local item_count = v * removed / entry_price.batchSize
if item_count > 0 then
red_invs[count].insert({name = k, count = item_count});
count = count + 1
else
log('Error (non-critical): item_count is not positive. v: ' .. v .. '; removed: ' .. removed .. '; entry_price.batchSize: ' .. entry_price.batchSize)
end
end
end
end
@ -402,8 +407,4 @@ function Public.tick_quest_structure_entry_price_check()
end
return Public

View File

@ -14,6 +14,7 @@ local Public = {}
local enum = {
DEFAULT = 'Default',
SLOT_ARTILLERY_SHELLS = 1,
SLOT_EXTRA_HOLD = 5,
SLOT_MORE_POWER = 6,
SLOT_RANDOM_CLASS = 7,
@ -104,11 +105,12 @@ Public.market_price_scale = 300
Public.cabin_shop_data = {
{
-- Note: coin price for this offer changes based on difficulty.
price = {{'coin', 4000}, {'coal', 20}, {'iron-plate', 20}},--should be inefficient on resources to merely buy arty to shoot nests
offer = {type='give-item', item = 'artillery-shell', count = 5},
},
{
price = {{'coin', 1000}, {'electronic-circuit', 20}},
price = {{'coin', 2000}, {'electronic-circuit', 50}},
offer = {type='give-item', item = 'rail-signal', count = 50},
},
{
@ -292,6 +294,8 @@ function Public.create_cabin_surface()
end
end
Public.update_captains_market_offers_based_on_difficulty(memory.difficulty_option)
rendering.draw_text(
{
color = {60, 255, 124},
@ -383,4 +387,29 @@ function Public.get_market_random_price(slot)
return nil
end
function Public.get_captains_market()
local surface = game.surfaces[Public.get_cabin_surface_name()]
return surface.find_entity('market', Public.Data.market_position)
end
function Public.update_captains_market_offers_based_on_difficulty(difficulty_option)
local market = Public.get_captains_market()
if market == nil then return end
local offers = market.get_market_items()
market.clear_market_items()
for i, offer in pairs(offers) do
if i == enum.SLOT_ARTILLERY_SHELLS then
for _, price in pairs(offer.price) do
if price.name == "coin" then
price.amount = difficulty_option * 1000
end
end
end
market.add_market_item(offer)
end
end
return Public

View File

@ -20,7 +20,7 @@ Public.Data = require 'maps.pirates.surfaces.islands.cave.data'
--lab-dark-1 > position has been copied
--lab-dark-2 > position has been visited
function Public.reveal(cave_miner, surface, source_surface, position, brushsize)
function Public.reveal(surface, source_surface, position, brushsize)
local source_tile = source_surface.get_tile(position)
if not source_tile.valid then return end
if source_tile.name == 'lab-dark-2' then return end
@ -66,7 +66,7 @@ function Public.reveal(cave_miner, surface, source_surface, position, brushsize)
for _, entity in pairs(source_surface.find_entities_filtered({area = {{position.x - brushsize, position.y - brushsize}, {position.x + brushsize, position.y + brushsize}}})) do
if entity.valid then
local entity_position = entity.position
local entity_position = {x = entity.position.x, y = entity.position.y}
if (position.x - entity_position.x) ^ 2 + (position.y - entity_position.y) ^ 2 < brushsize_square then
local e = entity.clone({position = entity_position, surface = surface})
if e and e.valid then
@ -98,7 +98,7 @@ function Public.reveal(cave_miner, surface, source_surface, position, brushsize)
Public.try_make_spawner_elite(e, destination)
Public.reveal(cave_miner, surface, source_surface, entity_position, 15)
Public.reveal(surface, source_surface, entity_position, 15)
end
end
end
@ -115,7 +115,7 @@ function Public.try_make_spawner_elite(spawner, destination)
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)
Common.new_healthbar(true, spawner, max_health, nil, max_health, 0.8, nil)
local elite_spawners = destination.dynamic_data.elite_spawners
if elite_spawners then
@ -245,7 +245,7 @@ local function on_player_changed_position(event)
local cave_miner = destination_data.dynamic_data.cave_miner
-- TODO: make more reliable way to get island surface
Public.reveal(cave_miner, player.surface, cave_miner.cave_surface, {x = Math.floor(player.position.x), y = Math.floor(player.position.y)}, 11)
Public.reveal(player.surface, cave_miner.cave_surface, {x = Math.floor(player.position.x), y = Math.floor(player.position.y)}, 11)
end
Event.add(defines.events.on_player_changed_position, on_player_changed_position)

View File

@ -376,7 +376,7 @@ function Public.spawn_enemy_boat(type)
boat.spawner = e
local max_health = Balance.biter_boat_health()
Common.new_healthbar(true, e, max_health, nil, max_health, 0.5, nil, destination.dynamic_data)
Common.new_healthbar(true, e, max_health, nil, max_health, 0.5, nil)
end
return enemyboats[#enemyboats]

View File

@ -274,32 +274,36 @@ local function radioactive_tick()
local tickinterval = 60
if destination.subtype == IslandEnum.enum.RADIOACTIVE then
-- faster evo (doesn't need difficulty scaling as higher difficulties have higher base evo):
local extra_evo = 0.22 * tickinterval/60 / Balance.expected_time_on_island()
Common.increment_evo(extra_evo)
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
-- Stop increasing evo when boat left the island
local surface_name = memory.boat and memory.boat.surface_name
if surface_name ~= memory.sea_name 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
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 = 6 * (Common.difficulty_scale()^(1.1) * (memory.overworldx/40)^(18/10) * (Balance.crew_scale())^(1/5)) / 3600 * tickinterval * (1 + (Common.difficulty_scale()-1)*0.2 + 0.001 * timer)
end
-- faster pollute:
local pollution = 0
local timer = destination.dynamic_data.timer
if timer and timer > 15 then
pollution = 6 * (Common.difficulty_scale()^(1.1) * (memory.overworldx/40)^(18/10) * (Balance.crew_scale())^(1/5)) / 3600 * tickinterval * (1 + (Common.difficulty_scale()-1)*0.2 + 0.001 * timer)
end
if pollution > 0 then
memory.floating_pollution = memory.floating_pollution + pollution
if pollution > 0 then
memory.floating_pollution = memory.floating_pollution + pollution
game.pollution_statistics.on_flow('uranium-ore', pollution)
end
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
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

View File

@ -161,7 +161,7 @@ local function walkways_tick()
if destination.subtype == IslandEnum.enum.WALKWAYS then
for _, player in pairs(game.connected_players) do
if player.force.name == memory.force_name and player.surface == game.surfaces[destination.surface_name] and player.character and player.character.valid and game.surfaces[destination.surface_name].get_tile(player.position).name == 'water-shallow' then
player.character.damage(12, game.forces['environment'], 'fire')
player.character.damage(Balance.walkways_frozen_pool_damage, game.forces['environment'], 'fire')
if not (player.character and player.character.valid) then
Common.notify_force(player.force, {'pirates.death_froze',player.name})
end

View File

@ -488,7 +488,7 @@ function Public.destination_on_crewboat_hits_shore(destination)
local spawner = Common.get_random_valid_spawner(surface)
if spawner then
local max_health = Balance.elite_spawner_health()
Common.new_healthbar(true, spawner, max_health, nil, max_health, 0.8, nil, destination.dynamic_data)
Common.new_healthbar(true, spawner, max_health, nil, max_health, 0.8, nil)
local elite_spawners = destination.dynamic_data.elite_spawners
if elite_spawners then