diff --git a/locale/en/journey.cfg b/locale/en/journey.cfg index b3bd2e84..7d51f902 100644 --- a/locale/en/journey.cfg +++ b/locale/en/journey.cfg @@ -1,4 +1,26 @@ [journey] map_info_main_caption=The Journey -map_info_sub_caption=v 1.8 -map_info_text=The selectors in the mothership, allow you to choose a destination.\nWorlds can be rerolled by spending a satellite at the top selector.\nOnce enough players are on a selector, mothership will start traveling.\n\nA teleporter will be deployed, after reaching the target.\nIt is however, only capable of transfering the subjects body.\n\nWorlds will get more difficult with each jump, stacking the chosen modifiers.\nLaunch uranium fuel cells via rocket cargo, to advance to the next world.\nThe tooltips on the top buttons yield informations about the current world.\nIf the journey ends, an admin can fully reset the map via command "/reset-journey".\n\nHow far will the journey lead? \ No newline at end of file +map_info_sub_caption=v 1.9 +map_info_text=The selectors in the mothership, allow you to choose a destination.\nWorlds can be rerolled by spending a satellite at the top selector.\nOnce enough players are on a selector, mothership will start traveling.\n\nA teleporter will be deployed, after reaching the target.\nIt is however, only capable of transfering the subjects body.\n\nWorlds will get more difficult with each jump, stacking the chosen modifiers.\nLaunch uranium fuel cells via rocket cargo, to advance to the next world.\nThe tooltips on the top buttons yield informations about the current world.\nIf the journey ends, an admin can fully reset the map via command "/journey-reset".\n\nHow far will the journey lead? + +tooltip_satellite=Satellites stored: __1__ / __2__\nSatellites are used by Mothership to scout for alternative destinations. +tooltip_nuclear_fuel=Emergency Reactors working: __1__ / __2__\n30 Emergency Reactors are usually damaged by Mothership if the current colony is determined to be lost and Mothership has to leave in a hurry.\nIf teleporter is lost and there is no emergency power, the game is over and run resets. +tooltip_fuel=Fuel requirement to advance to next world:\n__1__\n\nNuclear Fuel Cells in Mothership Cargo:\n__2__ +tooltip_delivery=Orbital Station Delivery: __1__ / __2__\nStation pays with one random starting item roll per time threshold.\nTimes: 120min, 240min, 480min, 960min, 1920min, 3840min\nCurrent time: __3__ minutes. + +beacon_hp=HP: __1__/10000 +teleporter=Personal Teleporter + +chunks_delete=Deleting chunks.. __1__ +mothership_format=[font=heading-1][color=255,155,155] [/color][/font][font=default-game][color=200,200,200]__1__[/color][/font] +world=World __1__ | __2__ +world_tooltip=__1__\n\n__2__\nCapsules:\n__3__ +tooltip_modifier=__1__ - __2__%\n +tooltip_capsule= __1__x [item=__2__] +tooltip_capsule2= __1__x [item=__2__]\n + +message_rocket_launched=Launching a rocket with __1__x [item=__2__] at [gps=__3__,__4__,nauvis]. +message_min_players=The minimal amount of players to vote for new world is set to __1__. +message_delivery_done=[img=item/__1__] Orbital Station delivery completed in __2__ minutes, granting __3__ loot rolls! +message_delivered=Delivered from Orbital Station: __2__x [img=item/__1__] added to capsule storage. +cmd_server_restarting=Server is restarting to apply updates to the scenario...Please reconnect in a minute. diff --git a/maps/journey/constants.lua b/maps/journey/constants.lua index e60c1e40..f8ac8102 100644 --- a/maps/journey/constants.lua +++ b/maps/journey/constants.lua @@ -1,8 +1,8 @@ ---luacheck: ignore + local Public = {} Public.mothership_teleporter_position = {x = 0, y = 12} -Public.teleporter_tile = "lab-dark-2" +Public.teleporter_tile = 'lab-dark-2' Public.mothership_radius = 48 @@ -13,7 +13,7 @@ for x = Public.mothership_radius * -1 - 32, Public.mothership_radius + 32, 1 do local distance = math.sqrt(position.x ^ 2 + position.y ^ 2) if distance > Public.mothership_radius then table.insert(Public.particle_spawn_vectors, {position.x, position.y}) - end + end end end Public.size_of_particle_spawn_vectors = #Public.particle_spawn_vectors @@ -23,8 +23,8 @@ Public.world_selector_height = 8 Public.max_satellites = 3 local area = { - left_top = {x = -3, y = math.floor(Public.mothership_radius * 0.5) * -1}, - right_bottom = {x = 3, y = math.floor(Public.mothership_radius * 0.5) * -1 + Public.world_selector_height}, + left_top = {x = -3, y = 4 + math.floor(Public.mothership_radius * 0.5) * -1}, + right_bottom = {x = 3, y = 4 + math.floor(Public.mothership_radius * 0.5) * -1 + Public.world_selector_height}, } Public.world_selector_areas = { @@ -53,149 +53,311 @@ Public.reroll_selector_area = { Public.mothership_messages = { waiting = { - "Return to me, so we can continue the journey!", - "Don't leave me waiting for so long. Let's continue our journey.", - "Please return to me.", - "Board me, so we can continue this adventure!", + 'Return to me, so we can continue the journey!', + 'Don\'t leave me waiting for so long. Let\'s continue our journey.', + 'Please return to me.', + 'Board me, so we can continue this adventure!', }, answers = { - "Yes, great idea.", - "Yes, wonderful.", - "Yes, definitely.", - "Yes, i love it!", - "The calculations say yes.", - "I don't know how to feel about this.", - "Ask again later, my processors are very busy.", - "No, this is certainly wrong.", - "No, i don't think so.", - "No, you are wrong.", - "No, that would be weird.", - "The calculations say no.", + 'Yes, great idea.', + 'Yes, wonderful.', + 'Yes, definitely.', + 'Yes, i love it!', + 'The calculations say yes.', + 'I don\'t know how to feel about this.', + 'Ask again later, my processors are very busy.', + 'No, this is certainly wrong.', + 'No, i don\'t think so.', + 'No, you are wrong.', + 'No, that would be weird.', + 'The calculations say no.', }, } Public.mothership_gen_settings = { - ["water"] = 0, - ["starting_area"] = 1, - ["cliff_settings"] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0}, - ["default_enable_all_autoplace_controls"] = false, - ["autoplace_settings"] = { - ["entity"] = {treat_missing_as_default = false}, - ["tile"] = {treat_missing_as_default = false}, - ["decorative"] = {treat_missing_as_default = false}, + ['water'] = 0, + ['starting_area'] = 1, + ['cliff_settings'] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0}, + ['default_enable_all_autoplace_controls'] = false, + ['autoplace_settings'] = { + ['entity'] = {treat_missing_as_default = false}, + ['tile'] = {treat_missing_as_default = false}, + ['decorative'] = {treat_missing_as_default = false}, }, autoplace_controls = { - ["coal"] = {frequency = 0, size = 0, richness = 0}, - ["stone"] = {frequency = 0, size = 0, richness = 0}, - ["copper-ore"] = {frequency = 0, size = 0, richness = 0}, - ["iron-ore"] = {frequency = 0, size = 0, richness = 0}, - ["uranium-ore"] = {frequency = 0, size = 0, richness = 0}, - ["crude-oil"] = {frequency = 0, size = 0, richness = 0}, - ["trees"] = {frequency = 0, size = 0, richness = 0}, - ["enemy-base"] = {frequency = 0, size = 0, richness = 0} + ['coal'] = {frequency = 0, size = 0, richness = 0}, + ['stone'] = {frequency = 0, size = 0, richness = 0}, + ['copper-ore'] = {frequency = 0, size = 0, richness = 0}, + ['iron-ore'] = {frequency = 0, size = 0, richness = 0}, + ['uranium-ore'] = {frequency = 0, size = 0, richness = 0}, + ['crude-oil'] = {frequency = 0, size = 0, richness = 0}, + ['trees'] = {frequency = 0, size = 0, richness = 0}, + ['enemy-base'] = {frequency = 0, size = 0, richness = 0} }, } -Public.modifiers = { - ["trees"] = {-20, -10, "Trees"}, - ["tree_durability"] = {-30, -15, "Tree Durability"}, - ["cliff_settings"] = {20, 40, "Cliffs"}, - ["water"] = {-20, -10, "Water"}, - ["coal"] = {-20, -10, "Coal"}, - ["stone"] = {-20, -10, "Stone"}, - ["iron-ore"] = {-20, -10, "Iron Ore"}, - ["copper-ore"] = {-20, -10, "Copper Ore"}, - ["crude-oil"] = {-20, -10, "Oil"}, - ["uranium-ore"] = {-20, -10, "Uranium Ore"}, - ["mixed_ore"] = {-20, -10, "Mixed Ore"}, - ["enemy-base"] = {10, 20, "Nests"}, - ["expansion_cooldown"] = {-30, -15, "Nest Expansion Cooldown"}, - ["enemy_attack_pollution_consumption_modifier"] = {-20, -10, "Nest Pollution Consumption"}, - ["max_unit_group_size"] = {15, 30, "Biter Group Size Maximum"}, - ["time_factor"] = {15, 30, "Evolution Time Factor"}, - ["destroy_factor"] = {15, 30, "Evolution Destroy Factor"}, - ["pollution_factor"] = {15, 30, "Evolution Pollution Factor"}, - ["ageing"] = {-20, -10, "Terrain Pollution Consumption"}, - ["diffusion_ratio"] = {10, 20, "Pollution Diffusion"}, - ["technology_price_multiplier"] = {10, 20, "Technology Price"}, +Public.modifiers = { + ['trees_size'] = {min = 0.01, max = 10, base = 1, dmin = -40, dmax = -20, name = 'Forest Sizes'}, + ['trees_richness'] = {min = 0.01, max = 10, base = 1, dmin = -40, dmax = -20, name = 'Amounts Of Trees'}, + ['trees_frequency'] = {min = 0.01, max = 10, base = 1, dmin = -40, dmax = -20, name = 'Forest Frequency'}, + ['tree_durability'] = {min = 0.1, max = 50, base = 30, dmin = -30, dmax =-15, name = 'Tree Durability'}, + ['ore_size'] = {min = 0.8, max = 10, base = 2, dmin = -10, dmax = -5, name = 'Ore Field Size'}, + ['ore_frequency'] = {min = 1, max = 1, base = 1, dmin = 0, dmax = 0, name = 'Ore Frequency', static = true}, + ['cliff_continuity'] = {min = 1, max = 10, base = 8, dmin = -30, dmax = -15, name = 'Cliff Continuity'}, + ['cliff_frequency'] = {min = 5, max = 80, base = 60, dmin = -30, dmax = -15, name = 'Cliff Frequency'}, + ['water'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Water'}, + ['coal'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Coal'}, + ['stone'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Stone'}, + ['iron-ore'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Iron Ore'}, + ['copper-ore'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Copper Ore'}, + ['crude-oil'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Oil'}, + ['uranium-ore'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Uranium Ore'}, + ['mixed_ore'] = {min = 0.01, max = 10, base = 1, dmin = -20, dmax = -10, name = 'Mixed Ore'}, + ['enemy_base_size'] = {min = 0.01, max = 10, base = 1, dmin = 20, dmax = 40, name = 'Nest Sizes'}, + ['enemy_base_richness'] = {min = 0.01, max = 10, base = 1, dmin = 20, dmax = 40, name = 'Nest Amounts'}, + ['enemy_base_frequency'] = {min = 0.01, max = 10, base = 1, dmin = 20, dmax = 40, name = 'Nest Frequency'}, + ['expansion_cooldown'] = {min = 3600, max = 28800, base = 14400, dmin = -20, dmax = -10, name = 'Nest Expansion Cooldown'}, + ['enemy_attack_pollution_consumption_modifier'] = {min = 0.25, max = 4, base = 1, dmin = -5, dmax = -2.5, name = 'Nest Pollution Consumption'}, + ['max_unit_group_size'] = {min = 10, max = 500, base = 100, dmin = 10, dmax = 20, name = 'Biter Group Size Maximum'}, + ['time_factor'] = {min = 0.000001, max = 0.0001, base = 0.000004, dmin = 15, dmax = 30, name = 'Evolution Time Factor'}, + ['destroy_factor'] = {min = 0.0002, max = 0.2, base = 0.002, dmin = 15, dmax = 30, name = 'Evolution Destroy Factor'}, + ['pollution_factor'] = {min = 0.00000009, max = 0.00009, base = 0.0000009, dmin = 15, dmax = 30, name = 'Evolution Pollution Factor'}, + ['ageing'] = {min = 0.01, max = 4, base = 1, dmin = -20, dmax = -10, name = 'Terrain Pollution Consumption'}, + ['diffusion_ratio'] = {min = 0.005, max = 0.05, base = 0.02, dmin = 10, dmax = 20, name = 'Pollution Diffusion'}, + ['technology_price_multiplier'] = {min = 0.05, max = 5, base = 0.5, dmin = 10, dmax = 20, name = 'Technology Price'}, + ['beacon_irritation'] = {min = 100, max = 1200, base = 900, dmin = -20, dmax = -10, name = 'Biter Attack Cooldown', static = true}, + ['starting_area'] = {min = 1, max = 1, base = 1, dmin = 0, dmax = 0, name = 'Starting Area Size', static = true} } Public.starter_goods_pool = { - {"accumulator", 8, 16}, - {"big-electric-pole", 8, 16}, - {"burner-inserter", 64, 128}, - {"burner-mining-drill", 8, 16}, - {"car", 2, 4}, - {"copper-cable", 128, 256}, - {"copper-plate", 64, 128}, - {"electric-furnace", 4, 8}, - {"electric-mining-drill", 4, 8}, - {"firearm-magazine", 64, 128}, - {"grenade", 8, 16}, - {"gun-turret", 4, 8}, - {"inserter", 32, 64}, - {"iron-gear-wheel", 64, 128}, - {"iron-plate", 64, 128}, - {"lab", 2, 4}, - {"long-handed-inserter", 32, 64}, - {"medium-electric-pole", 16, 32}, - {"pipe", 128, 256}, - {"radar", 4, 8}, - {"small-lamp", 64, 128}, - {"solar-panel", 8, 16}, - {"solid-fuel", 256, 512}, - {"stack-inserter", 16, 32}, - {"stack-filter-inserter", 16, 32}, - {"steam-turbine", 4, 8}, - {"steel-chest", 16, 32}, - {"steel-furnace", 8, 16}, - {"steel-plate", 32, 64}, - {"stone-wall", 128, 256}, - {"substation", 4, 8}, - {"green-wire", 256, 512}, - {"red-wire", 256, 512}, + ['basic'] = { + {'copper-cable', 128, 256}, + {'copper-plate', 64, 128}, + {'iron-gear-wheel', 64, 128}, + {'iron-plate', 64, 128}, + {'petroleum-gas-barrel', 20, 40}, + {'solid-fuel', 256, 512}, + {'steel-plate', 32, 64}, + {'electronic-circuit', 32, 64}, + }, + ['low'] = { + {'burner-inserter', 64, 128}, + {'burner-mining-drill', 8, 16}, + {'lab', 2, 4}, + {'steel-furnace', 8, 16}, + {'boiler', 2, 4}, + {'steam-engine', 4, 8}, + }, + ['mil'] = { + {'cliff-explosives', 10, 20}, + {'firearm-magazine', 64, 128}, + {'grenade', 8, 16}, + {'gun-turret', 4, 8}, + {'radar', 4, 8}, + {'stone-wall', 128, 256}, + {'gate', 32, 64}, + {'heavy-armor', 1, 1}, + {'modular-armor', 1, 1}, + {'shotgun-shell', 64, 128}, + {'defender-capsule', 12, 24}, + {'flamethrower-ammo', 20, 40}, + {'slowdown-capsule', 10, 20}, + }, + ['inter'] = { + {'big-electric-pole', 8, 16}, + {'car', 2, 4}, + {'electric-mining-drill', 4, 8}, + {'inserter', 32, 64}, + {'lab', 2, 4}, + {'long-handed-inserter', 32, 64}, + {'medium-electric-pole', 16, 32}, + {'pipe', 128, 256}, + {'small-lamp', 64, 128}, + {'steel-chest', 16, 32}, + {'transport-belt', 32, 64}, + {'pumpjack', 2, 4}, + }, + ['adv'] = { + {'accumulator', 8, 16}, + {'electric-furnace', 4, 8}, + {'solar-panel', 8, 16}, + {'stack-inserter', 16, 32}, + {'stack-filter-inserter', 16, 32}, + {'steam-turbine', 4, 8}, + {'substation', 4, 8}, + {'chemical-plant', 3, 6}, + {'oil-refinery', 1, 2}, + }, + ['rare'] = { + {'green-wire', 256, 512}, + {'red-wire', 256, 512}, + {'heat-exchanger', 1, 2}, + {'heat-pipe', 10, 20}, + {'nuclear-fuel', 4, 8}, + {'nuclear-reactor', 1, 1}, + {'advanced-circuit', 16, 32}, + {'construction-robot', 16, 32}, + {'personal-roboport-equipment', 1, 1}, + {'solar-panel-equipment', 2, 4}, + {'effectivity-module', 5, 10}, + }, } Public.build_type_whitelist = { - ["arithmetic-combinator"] = true, - ["constant-combinator"] = true, - ["decider-combinator"] = true, - ["electric-energy-interface"] = true, - ["electric-pole"] = true, - ["gate"] = true, - ["heat-pipe"] = true, - ["lamp"] = true, - ["pipe"] = true, - ["pipe-to-ground"] = true, - ["programmable-speaker"] = true, - ["transport-belt"] = true, - ["wall"] = true, + ['arithmetic-combinator'] = true, + ['constant-combinator'] = true, + ['decider-combinator'] = true, + ['electric-energy-interface'] = true, + ['electric-pole'] = true, + ['gate'] = true, + ['heat-pipe'] = true, + ['lamp'] = true, + ['pipe'] = true, + ['pipe-to-ground'] = true, + ['programmable-speaker'] = true, + ['transport-belt'] = true, + ['wall'] = true, } -Public.unique_world_traits = { - ["lush"] = {"Lush", "Pure Vanilla."}, - ["abandoned_library"] = {"Abandoned Library", "No blueprints to be found."}, - ["lazy_bastard"] = {"Lazy Bastard", "The machine does the job."}, - ["oceanic"] = {"Oceanic", "Arrrr, the flame turrets seem to malfunction in this climate."}, - ["ribbon"] = {"Ribbon", "Go right. (or left)"}, - ["wasteland"] = {"Wasteland", "Rusty treasures."}, - ["infested"] = {"Infested", "They lurk inside."}, - ["pitch_black"] = {"Pitch Black", "No light may reach this realm."}, - ["volcanic"] = {"Volcanic", "The floor is (almost) lava."}, - ["matter_anomaly"] = {"Matter Anomaly", "Why can't i hold all these ores.\nThe laser turret structures seem to malfunction."}, - ["mountainous"] = {"Mountainous", "Diggy diggy hole!"}, - ["eternal_night"] = {"Eternal Night", "This world seems to be missing a sun."}, - ["dense_atmosphere"] = {"Dense Atmosphere", "Your roboport structures seem to malfunction."}, - ["undead_plague"] = {"Undead Plague", "The dead are restless."}, - ["swamps"] = {"Swamps", "No deep water to be found in this world."}, - ["chaotic_resources"] = {"Chaotic Resources", "Something to sort out."}, - ["low_mass"] = {"Low Mass", "You feel light footed and the robots are buzzing."}, - ["eternal_day"] = {"Eternal Day", "The sun never moves."}, - ["quantum_anomaly"] = {"Quantum Anomaly", "Research complete."}, - ["replicant_fauna"] = {"Replicant Fauna", "The biters feed on your structures."}, - ["tarball"] = {"Tarball", "Door stuck, Door stuck..."}, - --[[ - ]] +Public.unique_world_traits = { + ['lush'] = { + name = 'Lush', + desc = 'Pure Vanilla.', + mods = 1, + loot = {basic = {1, 1}, low = {1, 1}, mil = {0, 1}, inter = {0, 1}, adv = {0, 0}, rare = {0, 0}} + }, + ['abandoned_library'] = { + name = 'Abandoned Library', + desc = 'No blueprints to be found.', + mods = 3, + loot = {basic = {0, 1}, low = {0, 1}, mil = {0, 1}, inter = {0, 1}, adv = {1, 1}, rare = {1, 1}} + }, + ['lazy_bastard'] = { + name = 'Lazy Bastard', + desc = 'The machine does the job.', + mods = 4, + loot = {basic = {0, 0}, low = {0, 0}, mil = {0, 1}, inter = {0, 2}, adv = {0, 1}, rare = {1, 1}} + }, + ['oceanic'] = { + name = 'Oceanic', + desc = 'Arrrr, the flame turrets seem to malfunction in this climate.', + mods = 2, + loot = {basic = {1, 1}, low = {0, 0}, mil = {0, 2}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['ribbon'] = { + name = 'Ribbon', + desc = 'Go right. (or left)', + mods = 4, + loot = {basic = {0, 0}, low = {0, 0}, mil = {0, 1}, inter = {0, 2}, adv = {0, 1}, rare = {1, 1}} + }, + ['wasteland'] = { + name = 'Wasteland', + desc = 'Rusty treasures.', + mods = 2, + loot = {basic = {0, 1}, low = {0, 1}, mil = {1, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['infested'] = { + name = 'Infested', + desc = 'They lurk inside.', + mods = 4, + loot = {basic = {0, 1}, low = {0, 0}, mil = {1, 1}, inter = {0, 2}, adv = {0, 2}, rare = {1, 1}} + }, + ['pitch_black'] = { + name = 'Pitch Black', + desc = 'No light may reach this realm.', + mods = 2, + loot = {basic = {1, 1}, low = {0, 1}, mil = {0, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['volcanic'] = { + name = 'Volcanic', + desc = 'The floor is (almost) lava.', + mods = 4, + loot = {basic = {0, 0}, low = {0, 0}, mil = {1, 1}, inter = {0, 2}, adv = {0, 2}, rare = {1, 1}} + }, + ['matter_anomaly'] = { + name = 'Matter Anomaly', + desc = 'Why can\'t I hold all these ores.\nThe laser turret structures seem to malfunction.', + mods = 2, + loot = {basic = {1, 1}, low = {0, 1}, mil = {1, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['mountainous'] = { + name = 'Mountainous', + desc = 'Diggy diggy hole!', + mods = 2, + loot = {basic = {1, 1}, low = {0, 1}, mil = {0, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['eternal_night'] = { + name = 'Eternal Night', + desc = 'This world seems to be missing a sun.', + mods = 2, + loot = {basic = {1, 1}, low = {0, 1}, mil = {0, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['dense_atmosphere'] = { + name = 'Dense Atmosphere', + desc = 'Your roboport structures seem to malfunction.', + mods = 3, + loot = {basic = {0, 1}, low = {0, 0}, mil = {0, 1}, inter = {1, 1}, adv = {0, 1}, rare = {1, 1}} + }, + ['undead_plague'] = { + name = 'Undead Plague', + desc = 'The dead are restless.', + mods = 4, + loot = {basic = {0, 0}, low = {0, 0}, mil = {1, 1}, inter = {0, 2}, adv = {0, 2}, rare = {1, 1}} + }, + ['swamps'] = { + name = 'Swamps', + desc = 'No deep water to be found in this world.', + mods = 3, + loot = {basic = {0, 1}, low = {0, 0}, mil = {0, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['chaotic_resources'] = { + name = 'Chaotic Resources', + desc = 'Something to sort out.', + mods = 2, + loot = {basic = {0, 1}, low = {0, 1}, mil = {0, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['low_mass'] = { + name = 'Low Mass', + desc = 'You feel light footed and the robots are buzzing.', + mods = 2, + loot = {basic = {0, 1}, low = {0, 1}, mil = {0, 0}, inter = {0, 2}, adv = {0, 1}, rare = {0, 1}} + }, + ['eternal_day'] = { + name = 'Eternal Day', + desc = 'The sun never moves.', + mods = 1, + loot = {basic = {1, 1}, low = {0, 1}, mil = {0, 0}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['quantum_anomaly'] = { + name = 'Quantum Anomaly', + desc = 'Research complete.', + mods = 2, + loot = {basic = {0, 0}, low = {0, 0}, mil = {0, 1}, inter = {1, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['replicant_fauna'] = { + name = 'Replicant Fauna', + desc = 'The biters feed on your structures.', + mods = 4, + loot = {basic = {0, 0}, low = {0, 0}, mil = {1, 1}, inter = {0, 1}, adv = {0, 1}, rare = {1, 1}} + }, + ['tarball'] = { + name = 'Tarball', + desc = 'Door stuck, Door stuck...', + mods = 4, + loot = {basic = {0, 0}, low = {0, 0}, mil = {0, 1}, inter = {0, 2}, adv = {0, 2}, rare = {1, 1}} + }, + ['railworld'] = { + name = 'Railworld', + desc = 'Long distances better travelled by train...', + mods = 3, + loot = {basic = {0, 1}, low = {0, 0}, mil = {0, 1}, inter = {0, 1}, adv = {0, 1}, rare = {0, 1}} + }, + ['resupply_station'] = { + name = 'Resupply Station', + desc = 'Local Orbital Station requires immediate resupply.\n Faster the delivery, more they pay.', + mods = 2, + loot = {basic = {0, 0}, low = {0, 0}, mil = {0, 1}, inter = {0, 2}, adv = {0, 2}, rare = {1, 1}} + }, } -return Public \ No newline at end of file +return Public diff --git a/maps/journey/functions.lua b/maps/journey/functions.lua index 3ad36f8e..7eb9c7d1 100644 --- a/maps/journey/functions.lua +++ b/maps/journey/functions.lua @@ -4,6 +4,7 @@ local Server = require 'utils.server' local Get_noise = require 'utils.get_noise' local Constants = require 'maps.journey.constants' local Unique_modifiers = require 'maps.journey.unique_modifiers' +local Vacants = require 'modules.clear_vacant_players' local math_sqrt = math.sqrt local math_random = math.random local math_floor = math.floor @@ -27,6 +28,12 @@ local function clear_selectors(journey) journey.reroll_selector.activation_level = 0 end +local function protect(entity, operable) + entity.minable = false + entity.destructible = false + entity.operable = operable +end + function Public.place_mixed_ore(event, journey) if math_random(1, 192) ~= 1 then return end local surface = event.surface @@ -37,37 +44,68 @@ function Public.place_mixed_ore(event, journey) Map_functions.draw_rainbow_patch({x = x, y = y}, surface, math_random(17, 22), base_amount * richness + 100) end -local function place_teleporter(journey, surface, position) +local function place_teleporter(journey, surface, position, build_beacon) local tiles = {} - for x = -1, 0, 1 do - for y = -1, 0, 1 do - local position = {x = position.x + x, y = position.y + y} - table.insert(tiles, {name = Constants.teleporter_tile, position = position}) + for x = -2, 2, 1 do + for y = -2, 2, 1 do + local pos = {x = position.x + x, y = position.y + y} + table.insert(tiles, {name = Constants.teleporter_tile, position = pos}) end end surface.set_tiles(tiles, false) - surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x - 1, y = position.y - 1}, target = {x = position.x + 1, y = position.y - 0.5}}) - surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x + 1, y = position.y - 1}, target = {x = position.x + 1, y = position.y + 1.5}}) - surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x + 1, y = position.y + 1}, target = {x = position.x - 1, y = position.y + 1.5}}) - surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x - 1, y = position.y + 1}, target = {x = position.x - 1, y = position.y - 0.5}}) - surface.destroy_decoratives({area = {{position.x - 1, position.y - 1}, {position.x + 1, position.y + 1}}}) + surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x - 1.5, y = position.y - 1.5}, target = {x = position.x + 2.5, y = position.y - 1.0}}) + surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x + 2.5, y = position.y - 1.5}, target = {x = position.x + 2.5, y = position.y + 3.0}}) + surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x + 2.5, y = position.y + 2.5}, target = {x = position.x - 1.5, y = position.y + 3.0}}) + surface.create_entity({name = 'electric-beam-no-sound', position = position, source = {x = position.x - 1.5, y = position.y + 2.5}, target = {x = position.x - 1.5, y = position.y - 1.0}}) + surface.destroy_decoratives({area = {{position.x - 3, position.y - 3}, {position.x + 3, position.y + 3}}}) + if build_beacon then + local beacon = surface.create_entity({name = 'beacon', position = {x = position.x, y = position.y}, force = 'player'}) + journey.beacon_objective_health = 10000 + beacon.operable = false + beacon.minable = false + beacon.active = false + rendering.draw_text { + text = {'journey.teleporter'}, + surface = surface, + target = beacon, + target_offset = {0, -1.5}, + color = {0, 1, 0}, + scale = 0.90, + font = 'default-game', + alignment = 'center', + scale_with_zoom = false + } + local hp = rendering.draw_text { + text = {'journey.beacon_hp', journey.beacon_objective_health}, + surface = surface, + target = beacon, + target_offset = {0, -1.0}, + color = {0, 1, 0}, + scale = 0.90, + font = 'default-game', + alignment = 'center', + scale_with_zoom = false + } + journey.beacon_objective = beacon + journey.beacon_objective_hp_label = hp + end end local function destroy_teleporter(journey, surface, position) local tiles = {} - for x = -1, 0, 1 do - for y = -1, 0, 1 do - local position = {x = position.x + x, y = position.y + y} - table.insert(tiles, {name = "lab-dark-1", position = position}) + for x = -2, 2, 1 do + for y = -2, 2, 1 do + local pos = {x = position.x + x, y = position.y + y} + table.insert(tiles, {name = 'lab-dark-1', position = pos}) end end surface.set_tiles(tiles, true) - for _, e in pairs(surface.find_entities_filtered({name = "electric-beam-no-sound", area = {{position.x - 1, position.y - 1}, {position.x + 1, position.y + 1}}})) do + for _, e in pairs(surface.find_entities_filtered({name = 'electric-beam-no-sound', area = {{position.x - 3, position.y - 3}, {position.x + 3, position.y + 3}}})) do e.destroy() end end -local function drop_player_items(player) +local function drop_player_items(journey, player) local character = player.character if not character then return end if not character.valid then return end @@ -81,7 +119,7 @@ local function drop_player_items(player) end local surface = player.surface - local spill_blockage = surface.create_entity{name = "stone-furnace", position = player.position} + local spill_blockage = surface.create_entity{name = 'oil-refinery', position = journey.beacon_objective.position or player.position} for _, define in pairs({defines.inventory.character_main, defines.inventory.character_guns, defines.inventory.character_ammo, defines.inventory.character_armor, defines.inventory.character_vehicle, defines.inventory.character_trash}) do local inventory = character.get_inventory(define) @@ -122,24 +160,53 @@ local function remove_offline_players(maximum_age_in_hours) game.remove_offline_players(players_to_remove) end -local function get_current_modifier_percentage(name, journey) +local function calc_modifier(journey, name) + return journey.world_modifiers[name] * (journey.world_specials[name] or 1) +end + +local function set_map_modifiers(journey) local mgs = game.surfaces.nauvis.map_gen_settings - for _, autoplace in pairs({"iron-ore", "copper-ore", "uranium-ore", "coal", "stone", "crude-oil", "stone", "trees", "enemy-base"}) do - if name == autoplace then return mgs.autoplace_controls[name].richness end + for _, name in pairs({'iron-ore', 'copper-ore', 'uranium-ore', 'coal', 'stone', 'crude-oil'}) do + mgs.autoplace_controls[name].richness = calc_modifier(journey, name) + mgs.autoplace_controls[name].size = calc_modifier(journey, 'ore_size') + mgs.autoplace_controls[name].frequency = calc_modifier(journey, 'ore_frequency') + end + journey.mixed_ore_richness = calc_modifier(journey, 'mixed_ore') + + mgs.autoplace_controls['trees'].richness = calc_modifier(journey, 'trees_richness') + mgs.autoplace_controls['trees'].size = calc_modifier(journey, 'trees_size') + mgs.autoplace_controls['trees'].frequency = calc_modifier(journey, 'trees_frequency') + mgs.autoplace_controls['enemy-base'].richness = calc_modifier(journey, 'enemy_base_richness') + mgs.autoplace_controls['enemy-base'].size = calc_modifier(journey, 'enemy_base_size') + mgs.autoplace_controls['enemy-base'].frequency = calc_modifier(journey, 'enemy_base_frequency') + mgs.starting_area = calc_modifier(journey, 'starting_area') + mgs.cliff_settings.cliff_elevation_interval = calc_modifier(journey, 'cliff_frequency') + mgs.cliff_settings.richness = calc_modifier(journey, 'cliff_continuity') + mgs.water = calc_modifier(journey, 'water') + game.map_settings.enemy_evolution['time_factor'] = calc_modifier(journey, 'time_factor') + game.map_settings.enemy_evolution['destroy_factor'] = calc_modifier(journey, 'destroy_factor') + game.map_settings.enemy_evolution['pollution_factor'] = calc_modifier(journey, 'pollution_factor') + game.map_settings.enemy_expansion.min_expansion_cooldown = calc_modifier(journey, 'expansion_cooldown') + game.map_settings.enemy_expansion.max_expansion_cooldown = calc_modifier(journey, 'expansion_cooldown') * 4 + game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = calc_modifier(journey, 'enemy_attack_pollution_consumption_modifier') + game.map_settings.pollution.ageing = calc_modifier(journey, 'ageing') + game.map_settings.pollution.diffusion_ratio = calc_modifier(journey, 'diffusion_ratio') + game.map_settings.pollution.min_pollution_to_damage_trees = calc_modifier(journey, 'tree_durability') * 6 + game.map_settings.pollution.pollution_restored_per_tree_damage = calc_modifier(journey, 'tree_durability') + game.map_settings.unit_group.max_unit_group_size = calc_modifier(journey, 'max_unit_group_size') + game.difficulty_settings.technology_price_multiplier = calc_modifier(journey, 'technology_price_multiplier') + game.surfaces.nauvis.map_gen_settings = mgs +end + +--raw == true returns directly the number +--raw == false returs ratio compared to default +local function get_modifier(name, journey, raw) + local value = calc_modifier(journey, name) + if raw then + return value + else + return value * (1 / (Constants.modifiers[name].base or 1)) end - if name == "cliff_settings" then return 40 / mgs.cliff_settings.cliff_elevation_interval end - if name == "water" then return mgs.water end - if name == "time_factor" then return game.map_settings.enemy_evolution.time_factor * 250000 end - if name == "destroy_factor" then return game.map_settings.enemy_evolution.destroy_factor * 500 end - if name == "pollution_factor" then return game.map_settings.enemy_evolution.pollution_factor * 1111000 end - if name == "expansion_cooldown" then return (game.map_settings.enemy_expansion.min_expansion_cooldown / 144) * 0.01 end - if name == "technology_price_multiplier" then return game.difficulty_settings.technology_price_multiplier * 2 end - if name == "enemy_attack_pollution_consumption_modifier" then return game.map_settings.pollution.enemy_attack_pollution_consumption_modifier end - if name == "ageing" then return game.map_settings.pollution.ageing end - if name == "diffusion_ratio" then return game.map_settings.pollution.diffusion_ratio * 50 end - if name == "tree_durability" then return game.map_settings.pollution.pollution_restored_per_tree_damage * 0.1 end - if name == "max_unit_group_size" then return game.map_settings.unit_group.max_unit_group_size * 0.005 end - if name == "mixed_ore" then return journey.mixed_ore_richness end end local function delete_nauvis_chunks(journey) @@ -148,12 +215,13 @@ local function delete_nauvis_chunks(journey) journey.nauvis_chunk_positions = {} for chunk in surface.get_chunks() do table.insert(journey.nauvis_chunk_positions, {chunk.x, chunk.y}) end journey.size_of_nauvis_chunk_positions = #journey.nauvis_chunk_positions - for _, e in pairs(surface.find_entities_filtered{type = "radar"}) do e.destroy() end + for _, e in pairs(surface.find_entities_filtered{type = 'radar'}) do e.destroy() end for _, player in pairs(game.players) do - local button = player.gui.top.add({type = "sprite-button", name = "chunk_progress", caption = ""}) - button.style.font = "heading-1" + local button = player.gui.top.add({type = 'sprite-button', name = 'chunk_progress', caption = ''}) + button.style.font = 'heading-1' button.style.font_color = {222, 222, 222} button.style.minimal_height = 38 + button.style.maximal_height = 38 button.style.minimal_width = 240 button.style.padding = -2 end @@ -171,7 +239,7 @@ local function delete_nauvis_chunks(journey) end end - local caption = "Deleting Chunks.. " .. journey.size_of_nauvis_chunk_positions + local caption = {'journey.chunks_delete', journey.size_of_nauvis_chunk_positions} for _, player in pairs(game.connected_players) do if player.gui.top.chunk_progress then player.gui.top.chunk_progress.caption = caption end end @@ -181,18 +249,16 @@ end function Public.mothership_message_queue(journey) local text = journey.mothership_messages[1] if not text then return end - if text ~= "" then - text = "[font=default-game][color=200,200,200]" .. text .. "[/color][/font]" - text = "[font=heading-1][color=255,155,155] [/color][/font]" .. text - game.print(text) + if text ~= '' then + game.print({'journey.mothership_format', text}) end table.remove(journey.mothership_messages, 1) end function Public.deny_building(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.name ~= "mothership" then return end + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.name ~= 'mothership' then return end if Constants.build_type_whitelist[entity.type] then entity.destructible = false return @@ -201,38 +267,83 @@ function Public.deny_building(event) end function Public.register_built_silo(event, journey) - local entity = event.created_entity - if not entity.valid then return end + local entity = event.created_entity + if not entity.valid then return end if entity.surface.index ~= 1 then return end - if entity.type ~= "rocket-silo" then return end + if entity.type ~= 'rocket-silo' then return end entity.auto_launch = false table.insert(journey.rocket_silos, entity) end +local function cargo_gui(name, itemname, tooltip, value, hidden) + for _, player in pairs(game.connected_players) do + if not player.gui.top[name] then + local frame = player.gui.top.add({type = 'frame', name = name}) + frame.style.left_margin = 0 + frame.style.padding = 0 + local sprite = frame.add({type = 'sprite', sprite = 'item/' .. itemname, name = name .. '_sprite', resize_to_sprite = false}) + sprite.style.minimal_width = 28 + sprite.style.minimal_height = 28 + sprite.style.maximal_width = 28 + sprite.style.maximal_height = 28 + sprite.style.margin = 0 + sprite.style.padding = 0 + local progressbar = frame.add({type = 'progressbar', name = name .. '_progressbar', value = 0}) + progressbar.style = 'achievement_progressbar' + progressbar.style.minimal_width = 100 + progressbar.style.maximal_width = 100 + progressbar.style.top_margin = 2 + progressbar.style.right_margin = 6 + end + local frame = player.gui.top[name] + frame.tooltip = tooltip + local sprite = player.gui.top[name][name .. '_sprite'] + sprite.sprite = 'item/' .. itemname + sprite.tooltip = tooltip + local progressbar = player.gui.top[name][name .. '_progressbar'] + progressbar.value = value + progressbar.tooltip = tooltip + if hidden then + frame.visible = false + else + frame.visible = true + end + end +end + +function Public.update_tooltips(journey) + local modiftt = {''} + for k, v in pairs(Constants.modifiers) do + modiftt = {'', modiftt, {'journey.tooltip_modifier', v.name, math.round(get_modifier(k, journey) * 100)}} + end + journey.tooltip_modifiers = modiftt + + local capsulett = {''} + local c = 0 + for k, v in pairs(journey.bonus_goods) do + c = c + 1 + if c % 3 == 0 then + capsulett = {'', capsulett, {'journey.tooltip_capsule2', v, k}} + else + capsulett = {'', capsulett, {'journey.tooltip_capsule', v, k}} + end + end + journey.tooltip_capsules = capsulett +end + function Public.draw_gui(journey) local surface = game.surfaces.nauvis local mgs = surface.map_gen_settings - local caption = "World " .. journey.world_number .. " | " .. Constants.unique_world_traits[journey.world_trait][1] - local tooltip = Constants.unique_world_traits[journey.world_trait][2] .. "\n\n" - - for k, v in pairs(Constants.modifiers) do - tooltip = tooltip .. v[3] .. " - " .. math.round(get_current_modifier_percentage(k, journey) * 100, 1) .. "%\n" - end - - tooltip = tooltip .. "\nCapsules:\n" - local c = 0 - for k, v in pairs(journey.bonus_goods) do - tooltip = tooltip .. v .. "x " .. k .. " " - c = c + 1 - if c % 2 == 0 then tooltip = tooltip .. "\n" end - end + local caption = {'journey.world', journey.world_number, Constants.unique_world_traits[journey.world_trait].name} + local tooltip = {'journey.world_tooltip', Constants.unique_world_traits[journey.world_trait].desc, journey.tooltip_modifiers, journey.tooltip_capsules} for _, player in pairs(game.connected_players) do if not player.gui.top.journey_button then - local element = player.gui.top.add({type = "sprite-button", name = "journey_button", caption = ""}) - element.style.font = "heading-1" + local element = player.gui.top.add({type = 'sprite-button', name = 'journey_button', caption = ''}) + element.style.font = 'heading-1' element.style.font_color = {222, 222, 222} element.style.minimal_height = 38 + element.style.maximal_height = 38 element.style.minimal_width = 250 element.style.padding = -2 end @@ -241,70 +352,31 @@ function Public.draw_gui(journey) gui.tooltip = tooltip end - local fuel_requirement = journey.mothership_cargo_space["uranium-fuel-cell"] + local fuel_requirement = journey.mothership_cargo_space['uranium-fuel-cell'] local value if fuel_requirement == 0 then value = 1 else - value = journey.mothership_cargo["uranium-fuel-cell"] / fuel_requirement + value = journey.mothership_cargo['uranium-fuel-cell'] / fuel_requirement end - local tooltip = "Fuel requirement to advance to next world:\n" .. fuel_requirement .. "\n\nNuclear Fuel Cells in Mothership Cargo:\n" .. journey.mothership_cargo["uranium-fuel-cell"] + cargo_gui('journey_fuel', 'uranium-fuel-cell', {'journey.tooltip_fuel', fuel_requirement, journey.mothership_cargo['uranium-fuel-cell']}, value) - for _, player in pairs(game.connected_players) do - if not player.gui.top.journey_fuel then - local frame = player.gui.top.add({type = 'frame', name = 'journey_fuel'}) - frame.style.padding = 0 - local element = frame.add({type = 'sprite', sprite = 'item/uranium-fuel-cell', name = "journey_fuel_sprite"}) - element.style.minimal_width = 32 - element.style.minimal_height = 32 - element.style.maximal_width = 32 - element.style.maximal_height = 32 - element.style.margin = 0 - element.style.padding = 0 - local element = frame.add({type = 'progressbar', name = 'journey_fuel_progressbar', value = 0}) - element.style.minimal_width = 100 - element.style.maximal_width = 100 - element.style.top_margin = 12 - element.style.right_margin = 12 - end - local gui = player.gui.top.journey_fuel - gui.tooltip = tooltip - local gui = player.gui.top.journey_fuel.journey_fuel_sprite - gui.tooltip = tooltip - local gui = player.gui.top.journey_fuel.journey_fuel_progressbar - gui.value = value - gui.tooltip = tooltip - end + local max_satellites = journey.mothership_cargo_space['satellite'] + local value2 = journey.mothership_cargo['satellite'] / max_satellites + cargo_gui('journey_satellites', 'satellite', {'journey.tooltip_satellite', journey.mothership_cargo['satellite'], max_satellites}, value2) - local max_sattelites = journey.mothership_cargo_space["satellite"] - local value = journey.mothership_cargo["satellite"] / max_sattelites - local tooltip = "Room for satellites in Mothership cargo:\n" .. max_sattelites .. "\n\nSatellites stored:\n" .. journey.mothership_cargo["satellite"] + local max_emergency_fuel = journey.mothership_cargo_space['nuclear-reactor'] + local value3 = journey.mothership_cargo['nuclear-reactor'] / max_emergency_fuel + cargo_gui('journey_emergency', 'nuclear-reactor', {'journey.tooltip_nuclear_fuel', journey.mothership_cargo['nuclear-reactor'], max_emergency_fuel}, value3) - for _, player in pairs(game.connected_players) do - if not player.gui.top.journey_satellites then - local frame = player.gui.top.add({type = 'frame', name = 'journey_satellites'}) - frame.style.left_margin = 4 - frame.style.padding = 0 - local element = frame.add({type = 'sprite', sprite = 'item/satellite', name = "journey_satellites_sprite"}) - element.style.minimal_width = 32 - element.style.minimal_height = 32 - element.style.maximal_width = 32 - element.style.maximal_height = 32 - element.style.margin = 0 - element.style.padding = 0 - local element = frame.add({type = 'progressbar', name = 'journey_satellites_progressbar', value = 0}) - element.style.minimal_width = 100 - element.style.maximal_width = 100 - element.style.top_margin = 12 - element.style.right_margin = 12 - end - local gui = player.gui.top.journey_satellites - gui.tooltip = tooltip - local gui = player.gui.top.journey_satellites.journey_satellites_sprite - gui.tooltip = tooltip - local gui = player.gui.top.journey_satellites.journey_satellites_progressbar - gui.value = value - gui.tooltip = tooltip + local item = journey.speedrun.item + local time = math.round(journey.speedrun.time / 6) / 10 + local speedgoal = journey.mothership_cargo_space[item] or 1 + local value4 = (journey.mothership_cargo[item] or 0) / speedgoal + if journey.speedrun.enabled then + cargo_gui('journey_delivery', item, {'journey.tooltip_delivery', journey.mothership_cargo[item] or 0, speedgoal, time}, value4) + else + cargo_gui('journey_delivery', item, {'journey.tooltip_delivery', journey.mothership_cargo[item] or 0, speedgoal, time}, value4, true) end end @@ -329,16 +401,56 @@ function Public.on_mothership_chunk_generated(event) for y = 0, 31, 1 do local position = {x = left_top.x + x, y = left_top.y + y} if is_mothership(position) then - table.insert(tiles, {name = "black-refined-concrete", position = position}) + table.insert(tiles, {name = 'black-refined-concrete', position = position}) else - table.insert(tiles, {name = "out-of-map", position = position}) + table.insert(tiles, {name = 'out-of-map', position = position}) end end end surface.set_tiles(tiles, true) end +function Public.export_journey(journey) + local data = { + world_number = journey.world_number, + world_modifiers = journey.world_modifiers, + bonus_goods = journey.bonus_goods, + world_selectors = journey.world_selectors, + mothership_cargo = journey.mothership_cargo, + mothership_cargo_space = journey.mothership_cargo_space, + } + local secs = Server.get_current_time() + if not secs then + return + else + Server.set_data('scenario_settings', 'journey_data', data) + game.print('Journey data exported...') + end +end + + +function Public.import_journey(journey) + local state = journey.game_state + if state == 'world' or state == 'dispatch_goods' or state == 'mothership_waiting_for_players' then + log('Can run import command only during world selection stages') + return + end + local secs = Server.get_current_time() + if not secs then + return + else + Server.try_get_data('scenario_settings', 'journey_data', journey.import) + end +end + function Public.hard_reset(journey) + if journey.restart_from_scenario then + game.print({'journey.cmd_server_restarting'}, {r = 255, g = 255, b = 0}) + Public.export_journey(journey) + Server.start_scenario('Journey') + return + end + Vacants.reset() if game.surfaces.mothership and game.surfaces.mothership.valid then game.delete_surface(game.surfaces.mothership) end @@ -349,41 +461,21 @@ function Public.hard_reset(journey) game.map_settings.enemy_expansion.max_expansion_distance = 20 game.map_settings.enemy_expansion.settler_group_min_size = 5 game.map_settings.enemy_expansion.settler_group_max_size = 50 - game.map_settings.enemy_expansion.min_expansion_cooldown = 14400 - game.map_settings.enemy_expansion.max_expansion_cooldown = 216000 game.map_settings.pollution.enabled = true - game.map_settings.pollution.ageing = 1 - game.map_settings.pollution.diffusion_ratio = 0.02 - game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = 1 - game.map_settings.pollution.min_pollution_to_damage_trees = 60 - game.map_settings.pollution.pollution_restored_per_tree_damage = 10 + game.map_settings.pollution.min_to_diffuse = 75 + game.map_settings.pollution.expected_max_per_chunk = 300 - game.map_settings.unit_group.max_unit_group_size = 200 - - game.difficulty_settings.technology_price_multiplier = 0.5 - - game.map_settings.enemy_evolution.time_factor = 0.000004 - game.map_settings.enemy_evolution.destroy_factor = 0.002 - game.map_settings.enemy_evolution.pollution_factor = 0.0000009 + game.map_settings.enemy_expansion.max_expansion_distance = 5 --default 7 + game.map_settings.enemy_expansion.friendly_base_influence_radius = 1 --default 2 + game.map_settings.enemy_expansion.enemy_building_influence_radius = 5 --default 2 + game.map_settings.enemy_expansion.building_coefficient = 0.02 --default 0.1 + game.map_settings.enemy_expansion.neighbouring_chunk_coefficient = 0.25 --defualt 0.5 + game.map_settings.enemy_expansion.neighbouring_base_chunk_coefficient = 0.25 --default 0.4 local surface = game.surfaces[1] - local mgs = surface.map_gen_settings - mgs.water = 1 - mgs.starting_area = 1 - mgs.cliff_settings = {cliff_elevation_interval = 40, cliff_elevation_0 = 10} - mgs.autoplace_controls = { - ["coal"] = {frequency = 1, size = 1, richness = 1}, - ["stone"] = {frequency = 1, size = 1, richness = 1}, - ["copper-ore"] = {frequency = 1, size = 1, richness = 1}, - ["iron-ore"] = {frequency = 1, size = 1, richness = 1}, - ["uranium-ore"] = {frequency = 1, size = 1, richness = 1}, - ["crude-oil"] = {frequency = 1, size = 1, richness = 1}, - ["trees"] = {frequency = 1, size = 1, richness = 1}, - ["enemy-base"] = {frequency = 1, size = 1, richness = 1}, - } - surface.map_gen_settings = mgs - surface.clear(true) + + surface.clear(true) surface.daytime = math.random(1, 100) * 0.01 if journey.world_selectors and journey.world_selectors[1].border then @@ -404,25 +496,43 @@ function Public.hard_reset(journey) journey.mixed_ore_richness = 1 journey.mothership_messages = {} journey.mothership_cargo = {} - journey.mothership_cargo["uranium-fuel-cell"] = 10 - journey.mothership_cargo["satellite"] = 1 + journey.mothership_cargo['uranium-fuel-cell'] = 10 + journey.mothership_cargo['satellite'] = 1 + journey.mothership_cargo['nuclear-reactor'] = 60 journey.mothership_cargo_space = { - ["satellite"] = 1, - ["uranium-fuel-cell"] = 0, + ['satellite'] = 1, + ['uranium-fuel-cell'] = 0, + ['nuclear-reactor'] = 60 } journey.bonus_goods = {} + journey.tooltip_capsules = '' + journey.tooltip_modifiers = '' journey.nauvis_chunk_positions = nil + journey.beacon_objective_health = 10000 + journey.beacon_objective_resistance = 0.9 + journey.beacon_timer = 0 journey.world_number = 0 - journey.world_trait = "lush" - journey.game_state = "create_mothership" + journey.world_trait = 'lush' + journey.world_modifiers = {} + journey.world_specials = {} + journey.emergency_triggered = false + journey.emergency_selected = false + journey.game_state = 'create_mothership' + journey.speedrun = {enabled = false, time = 0, item = 'iron-stick'} + journey.vote_minimum = 1 + journey.mothership_messages_last_damage = game.tick + for k, modifier in pairs(Constants.modifiers) do + journey.world_modifiers[k] = modifier.base + end + Public.update_tooltips(journey) end function Public.create_mothership(journey) - local surface = game.create_surface("mothership", Constants.mothership_gen_settings) + local surface = game.create_surface('mothership', Constants.mothership_gen_settings) surface.request_to_generate_chunks({x = 0, y = 0}, 6) surface.force_generate_chunk_requests() surface.freeze_daytime = true - journey.game_state = "draw_mothership" + journey.game_state = 'draw_mothership' end function Public.draw_mothership(journey) @@ -439,18 +549,17 @@ function Public.draw_mothership(journey) table.shuffle_table(positions) for _, position in pairs(positions) do - if surface.count_tiles_filtered({area = {{position.x - 1, position.y - 1}, {position.x + 2, position.y + 2}}, name = "out-of-map"}) > 0 then - local e = surface.create_entity({name = "stone-wall", position = position, force = "player"}) - e.destructible = false - e.minable = false + if surface.count_tiles_filtered({area = {{position.x - 1, position.y - 1}, {position.x + 2, position.y + 2}}, name = 'out-of-map'}) > 0 then + local e = surface.create_entity({name = 'stone-wall', position = position, force = 'player'}) + protect(e, true) end - if surface.count_tiles_filtered({area = {{position.x - 1, position.y - 1}, {position.x + 2, position.y + 2}}, name = "lab-dark-1"}) < 4 then - surface.set_tiles({{name = "lab-dark-1", position = position}}, true) + if surface.count_tiles_filtered({area = {{position.x - 1, position.y - 1}, {position.x + 2, position.y + 2}}, name = 'lab-dark-1'}) < 4 then + surface.set_tiles({{name = 'lab-dark-1', position = position}}, true) end end for _, tile in pairs(surface.find_tiles_filtered({area = {{Constants.mothership_teleporter_position.x - 2, Constants.mothership_teleporter_position.y - 2}, {Constants.mothership_teleporter_position.x + 2, Constants.mothership_teleporter_position.y + 2}}})) do - surface.set_tiles({{name = "lab-dark-1", position = tile.position}}, true) + surface.set_tiles({{name = 'lab-dark-1', position = tile.position}}, true) end for k, area in pairs(Constants.world_selector_areas) do @@ -500,77 +609,85 @@ function Public.draw_mothership(journey) only_in_alt_mode = false } - for k, item_name in pairs({"arithmetic-combinator", "constant-combinator", "decider-combinator", "programmable-speaker", "red-wire", "green-wire", "small-lamp", "substation", "pipe", "gate", "stone-wall", "transport-belt"}) do - local e = surface.create_entity({name = 'infinity-chest', position = {-7 + k, Constants.mothership_radius - 3}, force = 'player'}) - e.set_infinity_container_filter(1, {name = item_name, count = game.item_prototypes[item_name].stack_size}) - e.minable = false - e.destructible = false - e.operable = false - local e = surface.create_entity({name = "express-loader", position = {-7 + k, Constants.mothership_radius - 4}, force = "player"}) - e.minable = false - e.destructible = false - e.direction = 4 + for k, item_name in pairs({'arithmetic-combinator', 'constant-combinator', 'decider-combinator', 'programmable-speaker', 'red-wire', 'green-wire', 'small-lamp', 'substation', 'pipe', 'gate', 'stone-wall', 'transport-belt'}) do + local chest = surface.create_entity({name = 'infinity-chest', position = {-7 + k, Constants.mothership_radius - 3}, force = 'player'}) + chest.set_infinity_container_filter(1, {name = item_name, count = game.item_prototypes[item_name].stack_size}) + protect(chest, false) + local loader = surface.create_entity({name = 'express-loader', position = {-7 + k, Constants.mothership_radius - 4}, force = 'player'}) + protect(loader, true) + loader.direction = 4 end for m = -1, 1, 2 do - local e = surface.create_entity({name = "electric-energy-interface", position = {11 * m, Constants.mothership_radius - 4}, force = "player"}) - e.minable = false - e.destructible = false - local e = surface.create_entity({name = "substation", position = {9 * m, Constants.mothership_radius - 4}, force = "player"}) - e.minable = false - e.destructible = false + local inter = surface.create_entity({name = 'electric-energy-interface', position = {11 * m, Constants.mothership_radius - 4}, force = 'player'}) + protect(inter, true) + local sub = surface.create_entity({name = 'substation', position = {9 * m, Constants.mothership_radius - 4}, force = 'player'}) + protect(sub, true) end for m = -1, 1, 2 do local x = Constants.mothership_radius - 3 if m > 0 then x = x - 1 end local y = Constants.mothership_radius * 0.5 - 7 - local e = surface.create_entity({name = "artillery-turret", position = {x * m, y}, force = "player"}) - e.direction = 4 - e.minable = false - e.destructible = false - e.operable = false - local e = surface.create_entity({name = "burner-inserter", position = {(x - 1) * m, y}, force = "player"}) - e.direction = 4 + m * 2 - e.rotatable = false - e.minable = false - e.destructible = false - e.operable = false - local e = surface.create_entity({name = 'infinity-chest', position = {(x - 2) * m, y}, force = 'player'}) - e.set_infinity_container_filter(1, {name = "solid-fuel", count = 50}) - e.set_infinity_container_filter(2, {name = "artillery-shell", count = 1}) - e.minable = false - e.destructible = false - e.operable = false + local turret = surface.create_entity({name = 'artillery-turret', position = {x * m, y}, force = 'player'}) + turret.direction = 4 + protect(turret, false) + local ins = surface.create_entity({name = 'burner-inserter', position = {(x - 1) * m, y}, force = 'player'}) + ins.direction = 4 + m * 2 + ins.rotatable = false + protect(ins, false) + local chest = surface.create_entity({name = 'infinity-chest', position = {(x - 2) * m, y}, force = 'player'}) + chest.set_infinity_container_filter(1, {name = 'solid-fuel', count = 50}) + chest.set_infinity_container_filter(2, {name = 'artillery-shell', count = 1}) + protect(chest, false) end for _ = 1, 3, 1 do - local e = surface.create_entity({name = "compilatron", position = Constants.mothership_teleporter_position, force = "player"}) - e.destructible = false + local comp = surface.create_entity({name = 'compilatron', position = Constants.mothership_teleporter_position, force = 'player'}) + comp.destructible = false end - Public.draw_gui(journey) surface.daytime = 0.5 - journey.game_state = "set_world_selectors" + journey.game_state = 'set_world_selectors' end function Public.teleport_players_to_mothership(journey) local surface = game.surfaces.mothership for _, player in pairs(game.connected_players) do - if player.surface.name ~= "mothership" then + if player.surface.name ~= 'mothership' then Public.clear_player(player) - player.teleport(surface.find_non_colliding_position("character", {0,0}, 32, 0.5), surface) + player.teleport(surface.find_non_colliding_position('character', {0,0}, 32, 0.5), surface) journey.characters_in_mothership = journey.characters_in_mothership + 1 - table.insert(journey.mothership_messages, "Welcome home " .. player.name .. "!") + table.insert(journey.mothership_messages, 'Welcome home ' .. player.name .. '!') return end end end -local function get_activation_level(surface, area) - local player_count_in_area = surface.count_entities_filtered({area = area, name = "character"}) - local player_count_for_max_activation = #game.connected_players * 0.66 +function Public.set_minimum_to_vote(journey) + --server_id returns only on Comfy server + --therefore on Comfy, there is minimum of 3 players to vote for a world. + --in any multiplayer there is minimum of 2 players + --in singleplayer the minimum is 1 + --this does change only behaviour if there is less players connected than the minimum + --the minimum should actualize on player join or when mothership builds the selectors + if Server.get_server_id() ~= '' then + journey.vote_minimum = 3 + elseif game.is_multiplayer() then + journey.vote_minimum = 2 + else + journey.vote_minimum = 1 + end + local surface = game.surfaces.mothership + if #game.connected_players <= journey.vote_minimum and surface and surface.daytime <= 0.5 then + table.insert(journey.mothership_messages, {'journey.message_min_players', journey.vote_minimum}) + end +end + +local function get_activation_level(journey, surface, area) + local player_count_in_area = surface.count_entities_filtered({area = area, name = 'character'}) + local player_count_for_max_activation = math.max(#game.connected_players, journey.vote_minimum) * (2/3) local level = player_count_in_area / player_count_for_max_activation level = math.round(level, 2) return level @@ -598,50 +715,66 @@ local function draw_background(journey, surface) local speed = journey.mothership_speed for c = 1, 16 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] - surface.create_entity({name = "shotgun-pellet", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) + surface.create_entity({name = 'shotgun-pellet', position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end for c = 1, 16 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] - surface.create_entity({name = "piercing-shotgun-pellet", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) + surface.create_entity({name = 'piercing-shotgun-pellet', position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end for c = 1, 2 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] - surface.create_entity({name = "cannon-projectile", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) + surface.create_entity({name = 'cannon-projectile', position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end for c = 1, 1 * speed, 1 do local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] - surface.create_entity({name = "uranium-cannon-projectile", position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) + surface.create_entity({name = 'uranium-cannon-projectile', position = position, target = {position[1], position[2] + Constants.mothership_radius * 2}, speed = speed}) end if math.random(1, 32) == 1 then local position = Constants.particle_spawn_vectors[math.random(1, Constants.size_of_particle_spawn_vectors)] - surface.create_entity({name = "explosive-uranium-cannon-projectile", position = position, target = {position[1], position[2] + Constants.mothership_radius * 3}, speed = speed}) + surface.create_entity({name = 'explosive-uranium-cannon-projectile', position = position, target = {position[1], position[2] + Constants.mothership_radius * 3}, speed = speed}) end if math.random(1, 90) == 1 then local position_x = math.random(64, 160) local position_y = math.random(64, 160) if math.random(1, 2) == 1 then position_x = position_x * -1 end if math.random(1, 2) == 1 then position_y = position_y * -1 end - surface.create_entity({name = "big-worm-turret", position = {position_x, position_y}, force = "enemy"}) + surface.create_entity({name = 'big-worm-turret', position = {position_x, position_y}, force = 'enemy'}) end end +local function roll_bonus_goods(journey, trait, amount) + local loot = Constants.unique_world_traits[trait].loot + local bonus_goods = {} + while #bonus_goods < (amount or 3) do + for key, numbers in pairs(loot) do + local loot_table = Constants.starter_goods_pool[key] + if #bonus_goods < (amount or 3) and math.random(numbers[1], numbers[2]) >= 1 then + + local item = loot_table[math.random(1, #loot_table)] + bonus_goods[#bonus_goods + 1] = {item[1], math.random(item[2], item[3])} + end + end + end + return bonus_goods +end + function Public.set_world_selectors(journey) local surface = game.surfaces.mothership local x = Constants.reroll_selector_area.left_top.x + 3.2 journey.reroll_selector.texts = { rendering.draw_text{ - text = journey.mothership_cargo.satellite .. " x ", + text = journey.mothership_cargo.satellite .. ' x ', surface = surface, target = {x, Constants.reroll_selector_area.left_top.y - 1.5}, color = {255, 255, 255, 255}, scale = 1.5, - font = "default-large-bold", - alignment = "center", + font = 'default-large-bold', + alignment = 'center', scale_with_zoom = false, }, rendering.draw_sprite{ - sprite = "item/satellite", + sprite = 'item/satellite', surface = surface, y_scale = 1.5, x_scale = 1.5, @@ -650,13 +783,10 @@ function Public.set_world_selectors(journey) } local modifier_names = {} - for k, _ in pairs(Constants.modifiers) do - table.insert(modifier_names, k) - end - - local bonus_goods_keys = {} - for i = 1, #Constants.starter_goods_pool, 1 do - table.insert(bonus_goods_keys, i) + for k, v in pairs(Constants.modifiers) do + if not v.static then + table.insert(modifier_names, k) + end end local unique_world_traits = {} @@ -666,46 +796,86 @@ function Public.set_world_selectors(journey) table.shuffle_table(unique_world_traits) for k, world_selector in pairs(journey.world_selectors) do - table.shuffle_table(bonus_goods_keys) - table.shuffle_table(modifier_names) - world_selector.modifiers = {} - world_selector.bonus_goods = {} - world_selector.world_trait = unique_world_traits[k] - world_selector.fuel_requirement = math.random(25, 50) + if not journey.importing then + table.shuffle_table(modifier_names) + world_selector.modifiers = {} + world_selector.bonus_goods = {} + world_selector.world_trait = unique_world_traits[k] + world_selector.fuel_requirement = math.random(25, 50) + end local position = Constants.world_selector_areas[k].left_top local texts = world_selector.texts local modifiers = world_selector.modifiers - local bonus_goods = world_selector.bonus_goods - local y_modifier = -9.7 - - for i = 1, 8, 1 do + local y_modifier = -11.3 + local limits = {6, Constants.unique_world_traits[world_selector.world_trait].mods} + local counts = {0, 0} + local i = 1 + if journey.importing then goto skip_reroll end + while (limits[1] + limits[2] > counts[1] + counts[2]) and i < #modifier_names do local modifier = modifier_names[i] - local v = math.random(Constants.modifiers[modifier][1], Constants.modifiers[modifier][2]) - if i > 6 then v = v * -0.5 end - v = math.floor(v) - modifiers[i] = {modifier, v} + local data = Constants.modifiers[modifier] + local v + if journey.world_modifiers[modifier] >= data.max then + if data.dmin > 0 and counts[2] < limits[2] then + --at max, so we lower it as a positive modifier + v = math.floor(math.random(data.dmin, data.dmax) * -0.5) + counts[2] = counts[2] + 1 + modifiers[i] = {name = modifier, value = v, neg = false} + elseif data.dmin < 0 and counts[1] < limits[1] then + --at max, but it is good modifier, so lower it as negative modifier + v = math.floor(math.random(data.dmin, data.dmax)) + counts[1] = counts[1] + 1 + modifiers[i] = {name = modifier, value = v, neg = true} + end + elseif journey.world_modifiers[modifier] <= data.min then + if data.dmin < 0 and counts[1] < limits[1] then + --at min, but good to have it min, so we grow it as negative modifier + v = math.floor(math.random(data.dmin, data.dmax)) + counts[1] = counts[1] + 1 + modifiers[i] = {name = modifier, value = v, neg = true} + elseif data.dmin > 0 and counts[2] < limits[2] then + --at min, but min is bad, so we grow it as positive modifier + v = math.floor(math.random(data.dmin, data.dmax) * -0.5) + counts[2] = counts[2] + 1 + modifiers[i] = {name = modifier, value = v, neg = false} + end + else + --somewhere in middle, we first try to fill the positives then negatives. table is shuffled so it should be fine + if counts[2] < limits[2] then + v = math.floor(math.random(data.dmin, data.dmax) * -0.5) + counts[2] = counts[2] + 1 + modifiers[i] = {name = modifier, value = v, neg = false} + elseif counts[1] < limits[1] then + v = math.floor(math.random(data.dmin, data.dmax)) + counts[1] = counts[1] + 1 + modifiers[i] = {name = modifier, value = v, neg = true} + end + end + i = i + 1 end + world_selector.bonus_goods = roll_bonus_goods(journey, world_selector.world_trait) + ::skip_reroll:: table.insert(texts, rendering.draw_text{ - text = Constants.unique_world_traits[world_selector.world_trait][1], + text = Constants.unique_world_traits[world_selector.world_trait].name, surface = surface, target = {position.x + Constants.world_selector_width * 0.5, position.y + y_modifier}, color = {100, 0, 255, 255}, scale = 1.25, - font = "default-large-bold", - alignment = "center", + font = 'default-large-bold', + alignment = 'center', scale_with_zoom = false }) for k2, modifier in pairs(modifiers) do y_modifier = y_modifier + 0.8 - local text = "" - if modifier[2] > 0 then text = text .. "+" end - text = text .. modifier[2] .. "% " - text = text .. Constants.modifiers[modifier[1]][3] + local text = '' + if modifier.value > 0 then text = text .. '+' end + text = text .. modifier.value .. '% ' + text = text .. Constants.modifiers[modifier.name].name local color - if k2 < 7 then + if modifier.neg then color = {200, 0, 0, 255} else color = {0, 200, 0, 255} @@ -717,47 +887,41 @@ function Public.set_world_selectors(journey) target = {position.x + Constants.world_selector_width * 0.5, position.y + y_modifier}, color = color, scale = 1.25, - font = "default-large", - alignment = "center", + font = 'default-large', + alignment = 'center', scale_with_zoom = false }) end y_modifier = y_modifier + 0.85 table.insert(texts, rendering.draw_text{ - text = "Fuel requirement +" .. world_selector.fuel_requirement, + text = 'Fuel requirement +' .. world_selector.fuel_requirement, surface = surface, target = {position.x + Constants.world_selector_width * 0.5, position.y + y_modifier}, color = {155, 155, 0, 255}, scale = 1.25, - font = "default-large", - alignment = "center", + font = 'default-large', + alignment = 'center', scale_with_zoom = false }) table.insert(texts, rendering.draw_sprite{ - sprite = "item/uranium-fuel-cell", - surface = surface, - target = {position.x + Constants.world_selector_width * 0.5 + 3.7, position.y + y_modifier + 0.5}, + sprite = 'item/uranium-fuel-cell', + surface = surface, + target = {position.x + Constants.world_selector_width * 0.5 + 3.7, position.y + y_modifier + 0.5}, }) - for i = 1, 3, 1 do - local key = bonus_goods_keys[i] - local bonus_good = Constants.starter_goods_pool[key] - bonus_goods[i] = {bonus_good[1], math.random(bonus_good[2], bonus_good[3])} - end - y_modifier = y_modifier + 1.1 local x_modifier = -0.5 for k2, good in pairs(world_selector.bonus_goods) do local render_id = rendering.draw_text{ - text = "+" .. good[2], + text = '+' .. good[2], surface = surface, target = {position.x + x_modifier, position.y + y_modifier}, color = {200, 200, 0, 255}, scale = 1.25, - font = "default-large", - alignment = "center", + font = 'default-large', + alignment = 'center', scale_with_zoom = false } table.insert(texts, render_id) @@ -767,7 +931,7 @@ function Public.set_world_selectors(journey) if good[2] >= 100 then x_modifier = x_modifier + 0.18 end local render_id = rendering.draw_sprite{ - sprite = "item/" .. good[1], + sprite = 'item/' .. good[1], surface = surface, target = {position.x + x_modifier, position.y + 0.5 + y_modifier}, } @@ -780,9 +944,11 @@ function Public.set_world_selectors(journey) destroy_teleporter(journey, game.surfaces.nauvis, Constants.mothership_teleporter_position) destroy_teleporter(journey, surface, Constants.mothership_teleporter_position) - Server.to_discord_embed("World " .. journey.world_number + 1 .. " selection has started!") + Server.to_discord_embed('World ' .. journey.world_number + 1 .. ' selection has started!') + Public.set_minimum_to_vote(journey) + journey.importing = false - journey.game_state = "delete_nauvis_chunks" + journey.game_state = 'delete_nauvis_chunks' end function Public.delete_nauvis_chunks(journey) @@ -794,7 +960,7 @@ function Public.delete_nauvis_chunks(journey) if player.gui.top.chunk_progress then player.gui.top.chunk_progress.destroy() end end - journey.game_state = "mothership_world_selection" + journey.game_state = 'mothership_world_selection' end function Public.reroll_worlds(journey) @@ -802,10 +968,10 @@ function Public.reroll_worlds(journey) Public.teleport_players_to_mothership(journey) draw_background(journey, surface) animate_selectors(journey) - local reroll_selector_activation_level = get_activation_level(surface, Constants.reroll_selector_area) + local reroll_selector_activation_level = get_activation_level(journey, surface, Constants.reroll_selector_area) journey.reroll_selector.activation_level = reroll_selector_activation_level for i = 1, 3, 1 do - local activation_level = get_activation_level(surface, Constants.world_selector_areas[i]) + local activation_level = get_activation_level(journey, surface, Constants.world_selector_areas[i]) journey.world_selectors[i].activation_level = activation_level end if reroll_selector_activation_level > 1 then @@ -815,19 +981,31 @@ function Public.reroll_worlds(journey) clear_selectors(journey) journey.mothership_cargo.satellite = journey.mothership_cargo.satellite - 1 Public.draw_gui(journey) - table.insert(journey.mothership_messages, "New lands have been discovered!") - journey.game_state = "set_world_selectors" + table.insert(journey.mothership_messages, 'New lands have been discovered!') + journey.game_state = 'set_world_selectors' end else journey.mothership_speed = journey.mothership_speed - 0.25 if journey.mothership_speed < 0.35 then - table.insert(journey.mothership_messages, "Aborting..") - journey.game_state = "mothership_world_selection" + table.insert(journey.mothership_messages, 'Aborting..') + journey.game_state = 'mothership_world_selection' journey.mothership_speed = 0.35 end end end +function Public.importing_world(journey) + local surface = game.surfaces.mothership + Public.teleport_players_to_mothership(journey) + draw_background(journey, surface) + animate_selectors(journey) + clear_selectors(journey) + Public.update_tooltips(journey) + Public.draw_gui(journey) + table.insert(journey.mothership_messages, 'Restoring the last saved position...') + journey.game_state = 'set_world_selectors' +end + function Public.mothership_world_selection(journey) Public.teleport_players_to_mothership(journey) @@ -837,44 +1015,51 @@ function Public.mothership_world_selection(journey) if daytime < 0 then daytime = 0 end surface.daytime = daytime - local reroll_selector_activation_level = get_activation_level(surface, Constants.reroll_selector_area) + local reroll_selector_activation_level = get_activation_level(journey, surface, Constants.reroll_selector_area) journey.reroll_selector.activation_level = reroll_selector_activation_level - journey.selected_world = false - for i = 1, 3, 1 do - local activation_level = get_activation_level(surface, Constants.world_selector_areas[i]) - journey.world_selectors[i].activation_level = activation_level - if activation_level > 1 then - journey.selected_world = i + if journey.emergency_triggered then + if not journey.emergency_selected then + journey.selected_world = math.random(1, 3) + table.insert(journey.mothership_messages, 'Emergency destination selected..') + journey.emergency_selected = true + end + else + journey.selected_world = false + for i = 1, 3, 1 do + local activation_level = get_activation_level(journey, surface, Constants.world_selector_areas[i]) + journey.world_selectors[i].activation_level = activation_level + if activation_level > 1 then + journey.selected_world = i + end + end + if reroll_selector_activation_level > 1 and journey.mothership_speed == 0.35 and journey.mothership_cargo.satellite > 0 then + journey.game_state = 'reroll_worlds' + table.insert(journey.mothership_messages, 'Dispatching satellite..') + return end - end - - if reroll_selector_activation_level > 1 and journey.mothership_speed == 0.35 and journey.mothership_cargo.satellite > 0 then - journey.game_state = "reroll_worlds" - table.insert(journey.mothership_messages, "Dispatching satellite..") - return end if journey.selected_world then if not journey.mothership_advancing_to_world then - table.insert(journey.mothership_messages, "Advancing to selected world.") + table.insert(journey.mothership_messages, 'Advancing to selected world.') journey.mothership_advancing_to_world = game.tick + math.random(60 * 45, 60 * 75) else local seconds_left = math.floor((journey.mothership_advancing_to_world - game.tick) / 60) if seconds_left <= 0 then journey.mothership_advancing_to_world = false - table.insert(journey.mothership_messages, "Arriving at targeted destination!") - journey.game_state = "mothership_arrives_at_world" + table.insert(journey.mothership_messages, 'Arriving at targeted destination!') + journey.game_state = 'mothership_arrives_at_world' return end - if seconds_left % 15 == 0 then table.insert(journey.mothership_messages, "Estimated arrival in " .. seconds_left .. " seconds.") end + if seconds_left % 15 == 0 then table.insert(journey.mothership_messages, 'Estimated arrival in ' .. seconds_left .. ' seconds.') end end journey.mothership_speed = journey.mothership_speed + 0.1 if journey.mothership_speed > 4 then journey.mothership_speed = 4 end else if journey.mothership_advancing_to_world then - table.insert(journey.mothership_messages, "Aborting travelling sequence.") + table.insert(journey.mothership_messages, 'Aborting travelling sequence.') journey.mothership_advancing_to_world = false end journey.mothership_speed = journey.mothership_speed - 0.25 @@ -883,6 +1068,7 @@ function Public.mothership_world_selection(journey) draw_background(journey, surface) animate_selectors(journey) + Public.update_tooltips(journey) end function Public.mothership_arrives_at_world(journey) @@ -891,17 +1077,17 @@ function Public.mothership_arrives_at_world(journey) Public.teleport_players_to_mothership(journey) if journey.mothership_speed == 0.15 then - for _ = 1, 16, 1 do table.insert(journey.mothership_messages, "") end - table.insert(journey.mothership_messages, "[img=item/uranium-fuel-cell] Fuel cells depleted ;_;") - for _ = 1, 16, 1 do table.insert(journey.mothership_messages, "") end - table.insert(journey.mothership_messages, "Refuel via supply rocket required!") + for _ = 1, 16, 1 do table.insert(journey.mothership_messages, '') end + table.insert(journey.mothership_messages, '[img=item/uranium-fuel-cell] Fuel cells depleted ;_;') + for _ = 1, 16, 1 do table.insert(journey.mothership_messages, '') end + table.insert(journey.mothership_messages, 'Refuel via supply rocket required!') for i = 1, 3, 1 do journey.world_selectors[i].activation_level = 0 end animate_selectors(journey) - journey.game_state = "clear_modifiers" + journey.game_state = 'clear_modifiers' else journey.mothership_speed = journey.mothership_speed - 0.15 end @@ -909,21 +1095,25 @@ function Public.mothership_arrives_at_world(journey) if journey.mothership_speed < 0.15 then journey.mothership_speed = 0.15 end - + journey.beacon_objective_resistance = 0.90 - (0.03 * journey.world_number) + journey.emergency_triggered = false + journey.emergency_selected = false draw_background(journey, surface) + Public.update_tooltips(journey) end function Public.clear_modifiers(journey) local unique_modifier = Unique_modifiers[journey.world_trait] local clear = unique_modifier.clear if clear then clear(journey) end - + journey.world_specials = {} local force = game.forces.player force.reset() force.reset_technologies() force.reset_technology_effects() for a = 1, 7, 1 do force.technologies['refined-flammables-' .. a].enabled = false end - journey.game_state = "create_the_world" + journey.game_state = 'create_the_world' + Public.update_tooltips(journey) end function Public.create_the_world(journey) @@ -935,80 +1125,26 @@ function Public.create_the_world(journey) local modifiers = journey.world_selectors[journey.selected_world].modifiers for _, modifier in pairs(modifiers) do - local m = (100 + modifier[2]) * 0.01 - local name = modifier[1] - for _, autoplace in pairs({"iron-ore", "copper-ore", "uranium-ore", "coal", "stone", "crude-oil"}) do - if name == autoplace then - mgs.autoplace_controls[name].richness = mgs.autoplace_controls[name].richness * m - break - end - end - if name == "mixed_ore" then - journey.mixed_ore_richness = journey.mixed_ore_richness * m - end - for _, autoplace in pairs({"trees", "enemy-base"}) do - if name == autoplace then - for k, v in pairs(mgs.autoplace_controls[name]) do - mgs.autoplace_controls[name][k] = mgs.autoplace_controls[name][k] * m - end - break - end - end - if name == "cliff_settings" then - --smaller value = more cliffs - local m2 = (100 - modifier[2]) * 0.01 - mgs.cliff_settings.cliff_elevation_interval = mgs.cliff_settings.cliff_elevation_interval * m2 - mgs.cliff_settings.cliff_elevation_0 = mgs.cliff_settings.cliff_elevation_0 * m2 - end - if name == "water" then - mgs.water = mgs.water * m - end - for _, evo in pairs({"time_factor", "destroy_factor", "pollution_factor"}) do - if name == evo then - game.map_settings.enemy_evolution[name] = game.map_settings.enemy_evolution[name] * m - break - end - end - if name == "expansion_cooldown" then - game.map_settings.enemy_expansion.min_expansion_cooldown = game.map_settings.enemy_expansion.min_expansion_cooldown * m - game.map_settings.enemy_expansion.max_expansion_cooldown = game.map_settings.enemy_expansion.max_expansion_cooldown * m - end - if name == "technology_price_multiplier" then - game.difficulty_settings.technology_price_multiplier = game.difficulty_settings.technology_price_multiplier * m - end - if name == "enemy_attack_pollution_consumption_modifier" then - game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = game.map_settings.pollution.enemy_attack_pollution_consumption_modifier * m - end - if name == "ageing" then - game.map_settings.pollution.ageing = game.map_settings.pollution.ageing * m - end - if name == "diffusion_ratio" then - --recommended to keep the diffusion at 0 to 50%. Going over 100% eventually gives corrupted map due to pollution value overflows so needs to be capped - game.map_settings.pollution.diffusion_ratio = math.min(0.5, math.max(0, game.map_settings.pollution.diffusion_ratio * m)) - end - if name == "tree_durability" then - game.map_settings.pollution.min_pollution_to_damage_trees = game.map_settings.pollution.min_pollution_to_damage_trees * m - game.map_settings.pollution.pollution_restored_per_tree_damage = game.map_settings.pollution.pollution_restored_per_tree_damage * m - end - if name == "max_unit_group_size" then - game.map_settings.unit_group.max_unit_group_size = game.map_settings.unit_group.max_unit_group_size * m - end + local m = (100 + modifier.value) * 0.01 + local name = modifier.name + local extremes = {Constants.modifiers[name].min, Constants.modifiers[name].max} + journey.world_modifiers[name] = math.round(math.min(extremes[2], math.max(extremes[1], journey.world_modifiers[name] * m)), 5) end - surface.map_gen_settings = mgs - surface.clear(false) + set_map_modifiers(journey) + surface.clear(false) journey.world_trait = journey.world_selectors[journey.selected_world].world_trait journey.nauvis_chunk_positions = nil journey.rocket_silos = {} - journey.mothership_cargo["uranium-fuel-cell"] = 0 + journey.mothership_cargo['uranium-fuel-cell'] = 0 journey.world_number = journey.world_number + 1 local max_satellites = math_floor(journey.world_number * 0.334) + 1 if max_satellites > Constants.max_satellites then max_satellites = Constants.max_satellites end - journey.mothership_cargo_space["satellite"] = max_satellites - journey.mothership_cargo_space["uranium-fuel-cell"] = journey.mothership_cargo_space["uranium-fuel-cell"] + journey.world_selectors[journey.selected_world].fuel_requirement + journey.mothership_cargo_space['satellite'] = max_satellites + journey.mothership_cargo_space['uranium-fuel-cell'] = journey.mothership_cargo_space['uranium-fuel-cell'] + journey.world_selectors[journey.selected_world].fuel_requirement game.forces.enemy.reset_evolution() @@ -1022,46 +1158,46 @@ function Public.create_the_world(journey) journey.goods_to_dispatch = {} for k, v in pairs(journey.bonus_goods) do table.insert(journey.goods_to_dispatch, {k, v}) end table.shuffle_table(journey.goods_to_dispatch) - - journey.game_state = "wipe_offline_players" + Public.update_tooltips(journey) + journey.game_state = 'wipe_offline_players' end function Public.wipe_offline_players(journey) - remove_offline_players(168) + remove_offline_players(96) for _, player in pairs(game.players) do if not player.connected then player.force = game.forces.enemy end end - journey.game_state = "set_unique_modifiers" + journey.game_state = 'set_unique_modifiers' end function Public.notify_discord(journey) - if journey.disable_discord_notifications then - return - end - local caption = 'World ' .. journey.world_number .. ' | ' .. Constants.unique_world_traits[journey.world_trait][1] - local message = { - title = 'World advanced', - description = 'Arriving at target destination!', - color = 'warning', - field1 = { - text1 = 'World level:', - text2 = caption, - inline = 'true' - }, - field2 = { - text1 = 'World description:', - text2 = Constants.unique_world_traits[journey.world_trait][2], - inline = 'true' - }, - field3 = { - text1 = 'Fuel cells in mothership cargo:', - text2 = journey.mothership_cargo['uranium-fuel-cell'], - inline = 'false' - } - } - Server.to_discord_embed_parsed(message) + if journey.disable_discord_notifications then + return + end + local caption = 'World ' .. journey.world_number .. ' | ' .. Constants.unique_world_traits[journey.world_trait].name + local message = { + title = 'World advanced', + description = 'Arriving at target destination!', + color = 'warning', + field1 = { + text1 = 'World level:', + text2 = caption, + inline = 'true' + }, + field2 = { + text1 = 'World description:', + text2 = Constants.unique_world_traits[journey.world_trait].desc, + inline = 'true' + }, + field3 = { + text1 = 'Fuel cells in mothership cargo:', + text2 = journey.mothership_cargo['uranium-fuel-cell'], + inline = 'false' + } + } + Server.to_discord_embed_parsed(message) end @@ -1069,17 +1205,18 @@ function Public.set_unique_modifiers(journey) local unique_modifier = Unique_modifiers[journey.world_trait] local on_world_start = unique_modifier.on_world_start if on_world_start then on_world_start(journey) end + Public.update_tooltips(journey) Public.draw_gui(journey) Public.notify_discord(journey) - journey.game_state = "place_teleporter_into_world" + journey.game_state = 'place_teleporter_into_world' end function Public.place_teleporter_into_world(journey) local surface = game.surfaces.nauvis surface.request_to_generate_chunks({x = 0, y = 0}, 3) surface.force_generate_chunk_requests() - place_teleporter(journey, surface, Constants.mothership_teleporter_position) - journey.game_state = "make_it_night" + place_teleporter(journey, surface, Constants.mothership_teleporter_position, true) + journey.game_state = 'make_it_night' end function Public.make_it_night(journey) @@ -1091,9 +1228,9 @@ function Public.make_it_night(journey) if daytime > 0.5 then clear_selectors(journey) game.reset_time_played() - place_teleporter(journey, surface, Constants.mothership_teleporter_position) - table.insert(journey.mothership_messages, "Teleporter deployed. [gps=" .. Constants.mothership_teleporter_position.x .. "," .. Constants.mothership_teleporter_position.y .. ",mothership]") - journey.game_state = "dispatch_goods" + place_teleporter(journey, surface, Constants.mothership_teleporter_position, false) + table.insert(journey.mothership_messages, 'Teleporter deployed. [gps=' .. Constants.mothership_teleporter_position.x .. ',' .. Constants.mothership_teleporter_position.y .. ',mothership]') + journey.game_state = 'dispatch_goods' end end @@ -1105,11 +1242,11 @@ function Public.dispatch_goods(journey) local goods_to_dispatch = journey.goods_to_dispatch local size_of_goods_to_dispatch = #goods_to_dispatch if size_of_goods_to_dispatch == 0 then - for _ = 1, 30, 1 do table.insert(journey.mothership_messages, "") end - table.insert(journey.mothership_messages, "Capsule storage depleted.") - for _ = 1, 30, 1 do table.insert(journey.mothership_messages, "") end - table.insert(journey.mothership_messages, "Good luck on your adventure! ^.^") - journey.game_state = "world" + for _ = 1, 30, 1 do table.insert(journey.mothership_messages, '') end + table.insert(journey.mothership_messages, 'Capsule storage depleted.') + for _ = 1, 30, 1 do table.insert(journey.mothership_messages, '') end + table.insert(journey.mothership_messages, 'Good luck on your adventure! ^.^') + journey.game_state = 'world' return end @@ -1131,32 +1268,69 @@ function Public.dispatch_goods(journey) if math.abs(chunk.x) > 4 or math.abs(chunk.y) > 4 then return end local position = {x = chunk.x * 32 + math.random(0, 31), y = chunk.y * 32 + math.random(0, 31)} - position = surface.find_non_colliding_position("rocket-silo", position, 32, 1) + position = surface.find_non_colliding_position('rocket-silo', position, 32, 1) if not position then return end - journey.dispatch_beacon = surface.create_entity({name = "stone-wall", position = position, force = "neutral"}) + journey.dispatch_beacon = surface.create_entity({name = 'stone-wall', position = position, force = 'neutral'}) journey.dispatch_beacon.minable = false journey.dispatch_beacon_position = {x = position.x, y = position.y} journey.dispatch_key = math.random(1, size_of_goods_to_dispatch) local good = goods_to_dispatch[journey.dispatch_key] - table.insert(journey.mothership_messages, "Capsule containing " .. good[2] .. "x [img=item/" .. good[1] .. "] dispatched. [gps=" .. position.x .. "," .. position.y .. ",nauvis]") + table.insert(journey.mothership_messages, 'Capsule containing ' .. good[2] .. 'x [img=item/' .. good[1] .. '] dispatched. [gps=' .. position.x .. ',' .. position.y .. ',nauvis]') if journey.announce_capsules then - Server.to_discord_embed("A capsule containing " .. good[2] .. "x " .. good[1] .. " was spotted at: x=" .. position.x .. ", y=" .. position.y .. "!") + Server.to_discord_embed('A capsule containing ' .. good[2] .. 'x ' .. good[1] .. ' was spotted at: x=' .. position.x .. ', y=' .. position.y .. '!') end - surface.create_entity({name = "artillery-projectile", position = {x = position.x - 256 + math.random(0, 512), y = position.y - 256}, target = position, speed = 0.2}) + surface.create_entity({name = 'artillery-projectile', position = {x = position.x - 256 + math.random(0, 512), y = position.y - 256}, target = position, speed = 0.2}) end function Public.world(journey) - if journey.mothership_cargo["uranium-fuel-cell"] then - if journey.mothership_cargo["uranium-fuel-cell"] >= journey.mothership_cargo_space["uranium-fuel-cell"] then - table.insert(journey.mothership_messages, "[img=item/uranium-fuel-cell] Refuel operation successful!! =^.^=") - Server.to_discord_embed("Refuel operation complete!") - journey.game_state = "mothership_waiting_for_players" + if journey.mothership_cargo['uranium-fuel-cell'] then + if journey.mothership_cargo['uranium-fuel-cell'] >= journey.mothership_cargo_space['uranium-fuel-cell'] then + table.insert(journey.mothership_messages, '[img=item/uranium-fuel-cell] Refuel operation successful!! =^.^=') + Server.to_discord_embed('Refuel operation complete!') + journey.game_state = 'mothership_waiting_for_players' end end draw_background(journey, game.surfaces.mothership) + if journey.speedrun.enabled then + local item = journey.speedrun.item + local time = math.round(journey.speedrun.time / 6) / 10 + if journey.mothership_cargo[item] and journey.mothership_cargo[item] >= journey.mothership_cargo_space[item] then + local amount = 6 + local brackets = {120, 120, 240, 480, 960, 1920} + local timer = time + for i = 1, 6, 1 do + if timer >= brackets[i] then + timer = timer - brackets[i] + amount = amount - 1 + else + break + end + end + table.insert(journey.mothership_messages, {'journey.message_delivery_done', item, time, amount}) + Server.to_discord_embed({'journey.message_delivery_done', item, time, amount}, true) + local bonus_goods = roll_bonus_goods(journey, 'resupply_station', amount) + for _, good in pairs(bonus_goods) do + if journey.bonus_goods[good[1]] then + journey.bonus_goods[good[1]] = journey.bonus_goods[good[1]] + good[2] + else + journey.bonus_goods[good[1]] = good[2] + end + table.insert(journey.mothership_messages, {'journey.message_delivered', good[1], good[2]}) + end + Public.update_tooltips(journey) + journey.speedrun.enabled = false + end + if game.tick % 60 == 0 then + journey.speedrun.time = journey.speedrun.time + 1 + time = math.round(journey.speedrun.time / 6) / 10 + local speedgoal = journey.mothership_cargo_space[item] or 1 + local value = (journey.mothership_cargo[item] or 0) / speedgoal + cargo_gui('journey_delivery', item, {'journey.tooltip_delivery', journey.mothership_cargo[item] or 0, speedgoal, time}, value) + end + end if game.tick % 1800 ~= 0 then return end for k, silo in pairs(journey.rocket_silos) do @@ -1164,13 +1338,13 @@ function Public.world(journey) table.remove(journey.rocket_silos, k) break end - local inventory = silo.get_inventory(defines.inventory.rocket_silo_rocket) - if inventory then - local fuel_cells_required = journey.mothership_cargo_space["uranium-fuel-cell"] - journey.mothership_cargo["uranium-fuel-cell"] - if fuel_cells_required > 50 then fuel_cells_required = 50 end - if inventory.get_item_count('satellite') == 1 or inventory.get_item_count('uranium-fuel-cell') >= fuel_cells_required then + local inventory = silo.get_inventory(defines.inventory.rocket_silo_rocket) or {} + local slot = inventory[1] + if slot and slot.valid and slot.valid_for_read then + local needs = (journey.mothership_cargo_space[slot.name] or 0) - (journey.mothership_cargo[slot.name] or 0) + if needs > 0 and slot.count >= math.min(game.item_prototypes[slot.name].stack_size, needs) then if silo.launch_rocket() then - table.insert(journey.mothership_messages, "Launching rocket [gps=" .. silo.position.x .. "," .. silo.position.y .. ",nauvis]") + table.insert(journey.mothership_messages, {'journey.message_rocket_launched', slot.count, slot.name, silo.position.x, silo.position.y}) end end end @@ -1179,7 +1353,8 @@ end function Public.mothership_waiting_for_players(journey) if journey.characters_in_mothership > #game.connected_players * 0.5 then - journey.game_state = "set_world_selectors" + journey.game_state = 'set_world_selectors' + Vacants.reset() return end @@ -1195,11 +1370,12 @@ function Public.teleporters(journey, player) if not player.character then return end if not player.character.valid then return end local surface = player.surface - if surface.get_tile(player.position).name ~= Constants.teleporter_tile then return end + local tile = surface.get_tile(player.position) + if tile.name ~= Constants.teleporter_tile and tile.hidden_tile ~= Constants.teleporter_tile then return end local base_position = {0,0} if surface.index == 1 then - drop_player_items(player) - local position = game.surfaces.mothership.find_non_colliding_position("character", base_position, 32, 0.5) + drop_player_items(journey, player) + local position = game.surfaces.mothership.find_non_colliding_position('character', base_position, 32, 0.5) if position then player.teleport(position, game.surfaces.mothership) else @@ -1208,9 +1384,9 @@ function Public.teleporters(journey, player) journey.characters_in_mothership = journey.characters_in_mothership + 1 return end - if surface.name == "mothership" then + if surface.name == 'mothership' then Public.clear_player(player) - local position = game.surfaces.nauvis.find_non_colliding_position("character", base_position, 32, 0.5) + local position = game.surfaces.nauvis.find_non_colliding_position('character', base_position, 32, 0.5) if position then player.teleport(position, game.surfaces.nauvis) else @@ -1222,4 +1398,61 @@ function Public.teleporters(journey, player) end end +function Public.deal_damage_to_beacon(journey, incoming_damage) + if journey.game_state ~= 'world' then return end + local resistance = journey.beacon_objective_resistance + journey.beacon_objective_health = math.floor(journey.beacon_objective_health - (incoming_damage * (1 - resistance))) + rendering.set_text(journey.beacon_objective_hp_label, {'journey.beacon_hp', journey.beacon_objective_health}) + if journey.beacon_objective_health < 5000 and game.tick > journey.mothership_messages_last_damage + 900 then --under 50%, once every 15 seconds max + table.insert(journey.mothership_messages, 'The personal teleporter is being damaged, preparing for emergency departure.') + journey.mothership_messages_last_damage = game.tick + end + if journey.beacon_objective_health <= 0 then + table.insert(journey.mothership_messages, 'Beaming everyone up, triggerring emergency departure.') + table.insert(journey.mothership_messages, '[img=item/nuclear-reactor] Emergency power plant burned down ;_;') + journey.mothership_cargo['nuclear-reactor'] = journey.mothership_cargo['nuclear-reactor'] - 30 + if journey.mothership_cargo['nuclear-reactor'] < 0 then + table.insert(journey.mothership_messages, 'Aborting, there is not enough emergency fuel. Shutting systems off...') + for _ = 1, #journey.mothership_messages, 1 do + Public.mothership_message_queue(journey) + end + Public.hard_reset(journey) + else + journey.emergency_triggered = true + journey.game_state = 'set_world_selectors' + Public.update_tooltips(journey) + Public.draw_gui(journey) + end + end +end + +function Public.lure_biters(journey, position) + if journey.game_state ~= 'world' or not journey.beacon_objective.valid then return end + local beacon = journey.beacon_objective + local surface = beacon.surface + local biters = surface.find_entities_filtered{position = position or beacon.position, radius = 80, force = 'enemy', type = 'unit'} + if #biters > 0 then + for _, biter in pairs(biters) do + biter.set_command({type = defines.command.attack_area, destination = beacon.position, radius = 10, distraction = defines.distraction.by_anything}) + end + end + --return (#biters or 0) +end + +function Public.lure_far_biters(journey) + -- if journey.game_state ~= 'world' or not journey.beacon_objective.valid then return end + -- if journey.beacon_timer < journey.world_modifiers['beacon_irritation'] then + -- journey.beacon_timer = journey.beacon_timer + 10 + -- return + -- end + -- local surface = journey.beacon_objective.surface + -- local chunk_position = surface.get_random_chunk() + -- local lured = 0 + -- for _ = 1, 25, 1 do + -- lured = lured + Public.lure_biters(journey, {x = chunk_position.x * 32, y = chunk_position.y * 32}) + -- end + -- game.print('lured ' .. lured .. 'biters at tick ' .. game.tick) + -- journey.beacon_timer = journey.beacon_timer - lured +end + return Public diff --git a/maps/journey/main.lua b/maps/journey/main.lua index fa855eb7..2eef6512 100644 --- a/maps/journey/main.lua +++ b/maps/journey/main.lua @@ -1,4 +1,3 @@ ---luacheck: ignore --[[ Journey, launch a rocket in increasingly harder getting worlds. - MewMew ]]-- @@ -11,11 +10,18 @@ local Functions = require 'maps.journey.functions' local Unique_modifiers = require 'maps.journey.unique_modifiers' local Map = require 'modules.map_info' local Global = require 'utils.global' +local Token = require 'utils.token' +local Event = require 'utils.event' +local Vacants = require 'modules.clear_vacant_players' local journey = { announce_capsules = true } +local events = { + import = Event.generate_event_name('import'), +} + Global.register( journey, function(tbl) @@ -23,6 +29,15 @@ Global.register( end ) +journey.import = Token.register( + function(data) + if not data then + return + end + script.raise_event(events.import, data) + end +) + local function on_chunk_generated(event) local surface = event.surface @@ -33,40 +48,40 @@ local function on_chunk_generated(event) return end - if surface.name ~= "mothership" then return end + if surface.name ~= 'mothership' then return end Functions.on_mothership_chunk_generated(event) end local function on_console_chat(event) if not event.player_index then return end - local player = game.players[event.player_index] local message = event.message message = string.lower(message) - local a, b = string.find(message, "?", 1, true) - if not a then return end - local a, b = string.find(message, "mother", 1, true) + local a = string.find(message, '?', 1, true) if not a then return end + local b = string.find(message, 'mother', 1, true) + if not b then return end local answer = Constants.mothership_messages.answers[math.random(1, #Constants.mothership_messages.answers)] if math.random(1, 4) == 1 then - for _ = 1, math.random(2, 5), 1 do table.insert(journey.mothership_messages, "") end - table.insert(journey.mothership_messages, "...") + for _ = 1, math.random(2, 5), 1 do table.insert(journey.mothership_messages, '') end + table.insert(journey.mothership_messages, '...') end - for _ = 1, math.random(15, 30), 1 do table.insert(journey.mothership_messages, "") end + for _ = 1, math.random(15, 30), 1 do table.insert(journey.mothership_messages, '') end table.insert(journey.mothership_messages, answer) end local function on_player_joined_game(event) local player = game.players[event.player_index] Functions.draw_gui(journey) + Functions.set_minimum_to_vote(journey) - if player.surface.name == "mothership" then + if player.surface.name == 'mothership' then journey.characters_in_mothership = journey.characters_in_mothership + 1 end - if player.force.name == "enemy" then + if player.force.name == 'enemy' then Functions.clear_player(player) player.force = game.forces.player - local position = game.surfaces.nauvis.find_non_colliding_position("character", {0,0}, 32, 0.5) + local position = game.surfaces.nauvis.find_non_colliding_position('character', {0,0}, 32, 0.5) if position then player.teleport(position, game.surfaces.nauvis) else @@ -79,8 +94,9 @@ local function on_player_left_game(event) local player = game.players[event.player_index] Functions.draw_gui(journey) - if player.surface.name == "mothership" then + if player.surface.name == 'mothership' then journey.characters_in_mothership = journey.characters_in_mothership - 1 + player.clear_items_inside() end end @@ -115,6 +131,16 @@ local function on_robot_mined_entity(event) if unique_modifier.on_robot_mined_entity then unique_modifier.on_robot_mined_entity(event, journey) end end +local function on_entity_damaged(event) + local entity = event.entity + if not entity or not entity.valid then return end + if entity ~= journey.beacon_objective then return end + if event.force and event.force.name == 'enemy' then + Functions.deal_damage_to_beacon(journey, event.final_damage_amount) + end + entity.health = 200 +end + local function on_entity_died(event) local unique_modifier = Unique_modifiers[journey.world_trait] if unique_modifier.on_entity_died then unique_modifier.on_entity_died(event, journey) end @@ -133,17 +159,48 @@ local function on_rocket_launched(event) if journey.mothership_cargo[slot.name] > journey.mothership_cargo_space[slot.name] then journey.mothership_cargo[slot.name] = journey.mothership_cargo_space[slot.name] end - if slot.name == "uranium-fuel-cell" then - Server.to_discord_embed("Refueling progress: " .. journey.mothership_cargo[slot.name] .. "/" .. journey.mothership_cargo_space[slot.name]) - end + if slot.name == 'uranium-fuel-cell' or slot.name == 'nuclear-reactor' then + Server.to_discord_embed('Refueling progress: ' .. slot.name .. ': ' .. journey.mothership_cargo[slot.name] .. '/' .. journey.mothership_cargo_space[slot.name]) + elseif journey.speedrun.enabled and slot.name == journey.speedrun.item then + Server.to_discord_embed('Orbital Station delivery: ' .. slot.name .. ': ' .. journey.mothership_cargo[slot.name] .. '/' .. journey.mothership_cargo_space[slot.name]) + end end end Functions.draw_gui(journey) end +local function make_import(data) + if not data then + return + end + + if data.key ~= 'journey_data' then + return + end + local old_selectors = journey.world_selectors + for key, value in pairs(data.value) do + journey[key] = value + end + for k, selector in pairs(old_selectors) do + journey.world_selectors[k].border = selector.border + journey.world_selectors[k].texts = selector.texts + journey.world_selectors[k].rectangles = selector.rectangles + end + journey.importing = true + game.print('Journey data imported.') + journey.game_state = 'importing_world' +end + local function on_nth_tick() Functions[journey.game_state](journey) Functions.mothership_message_queue(journey) + local tick = game.tick + + if tick % 3600 == 0 then + Functions.lure_far_biters(journey) + elseif tick % 600 == 0 then + Functions.lure_biters(journey) + end end local function on_init() @@ -153,45 +210,86 @@ local function on_init() T.sub_caption_color = {r = 100, g = 100, b = 100} game.permissions.get_group('Default').set_allows_action(defines.input_action.set_auto_launch_rocket, false) - + Vacants.init(1, true) Functions.hard_reset(journey) end +local function cmd_handler() + local player = game.player + local p + if not (player and player.valid) then + p = log + else + p = player.print + end + if player and not player.admin then + p('You are not an admin!') + return false + end + return true, player or {name = 'Server'}, p +end + commands.add_command( - 'reset-journey', + 'journey-reset', 'Fully resets the journey map.', function() - local player = game.player - if not (player and player.valid) then - return - end - if not player.admin then - player.print("You are not an admin!") - return - end - Functions.hard_reset(journey) - game.print(player.name .. " has reset the map.") + local s, player = cmd_handler() + if s then + Functions.hard_reset(journey) + game.print(player.name .. ' has reset the map.') + end end ) commands.add_command( - 'skip-world', + 'journey-skip-world', 'Instantly wins and skips the current world.', function() - local player = game.player - if not (player and player.valid) then - return - end - if not player.admin then - player.print("You are not an admin!") - return - end - if journey.game_state ~= "dispatch_goods" and journey.game_state ~= "world" then return end - journey.game_state = "set_world_selectors" + local s, _, p = cmd_handler() + if s then + if journey.game_state ~= 'dispatch_goods' and journey.game_state ~= 'world' then return end + journey.game_state = 'set_world_selectors' + p('The current world was skipped...') + end + end +) + +commands.add_command( + 'journey-update', + 'Restarts the server with newest version of Journey scenario code during next map reset', + function() + local s, _, p = cmd_handler() + if s then + journey.restart_from_scenario = not journey.restart_from_scenario + p('Journey marking for full restart with updates on next reset was switched to ' .. tostring(journey.restart_from_scenario)) + end + end +) + +commands.add_command( + 'journey-import', + 'Sets the journey gamestate to the last exported one.', + function() + local s, _, p = cmd_handler() + if s then + Functions.import_journey(journey) + p('Journey world settings importing...') + end + end +) + +commands.add_command( + 'journey-export', + 'Exports the journey gamestate to the server', + function() + local s, _, p = cmd_handler() + if s then + Functions.export_journey(journey) + p('Journey world settings exporting...') + end end ) -local Event = require 'utils.event' Event.on_init(on_init) Event.on_nth_tick(10, on_nth_tick) Event.add(defines.events.on_chunk_generated, on_chunk_generated) @@ -204,4 +302,6 @@ Event.add(defines.events.on_built_entity, on_built_entity) Event.add(defines.events.on_robot_mined_entity, on_robot_mined_entity) Event.add(defines.events.on_player_mined_entity, on_player_mined_entity) Event.add(defines.events.on_entity_died, on_entity_died) +Event.add(defines.events.on_entity_damaged, on_entity_damaged) Event.add(defines.events.on_console_chat, on_console_chat) +Event.add(events['import'], make_import) diff --git a/maps/journey/unique_modifiers.lua b/maps/journey/unique_modifiers.lua index 8b936bd7..ea1fbdc1 100644 --- a/maps/journey/unique_modifiers.lua +++ b/maps/journey/unique_modifiers.lua @@ -1,4 +1,4 @@ ---luacheck: ignore +--luacheck: ignore 212/journey local Get_noise = require 'utils.get_noise' local BiterRaffle = require 'functions.biter_raffle' local LootRaffle = require 'functions.loot_raffle' @@ -32,8 +32,8 @@ local solid_tiles = { ['refined-hazard-concrete-left'] = true, ['refined-hazard-concrete-right'] = true, ['stone-path'] = true, - ["lab-dark-1"] = true, - ["lab-dark-2"] = true, + ['lab-dark-1'] = true, + ['lab-dark-2'] = true, } local wrecks = { 'crash-site-spaceship-wreck-big-1', @@ -49,455 +49,529 @@ local Public = {} Public.lush = {} Public.eternal_day = { - on_world_start = function(journey) - game.surfaces.nauvis.daytime = 0 - game.surfaces.nauvis.freeze_daytime = true - end, - clear = function(journey) - local surface = game.surfaces.nauvis - surface.freeze_daytime = false - end, + on_world_start = function(journey) + game.surfaces.nauvis.daytime = 0 + game.surfaces.nauvis.freeze_daytime = true + end, + clear = function(journey) + local surface = game.surfaces.nauvis + surface.freeze_daytime = false + end, } Public.eternal_night = { - on_world_start = function(journey) - local surface = game.surfaces.nauvis - surface.daytime = 0.44 - surface.freeze_daytime = true - surface.solar_power_multiplier = 5 - end, - clear = function(journey) - local surface = game.surfaces.nauvis - surface.freeze_daytime = false - surface.solar_power_multiplier = 1 - end, + on_world_start = function(journey) + local surface = game.surfaces.nauvis + surface.daytime = 0.44 + surface.freeze_daytime = true + surface.solar_power_multiplier = 5 + end, + clear = function(journey) + local surface = game.surfaces.nauvis + surface.freeze_daytime = false + surface.solar_power_multiplier = 1 + end, } Public.pitch_black = { - on_world_start = function(journey) - local surface = game.surfaces.nauvis - surface.daytime = 0.44 - surface.freeze_daytime = true - surface.solar_power_multiplier = 3 - surface.min_brightness = 0 - surface.brightness_visual_weights = {0.8, 0.8, 0.8, 1} - end, - clear = function(journey) - local surface = game.surfaces.nauvis - surface.freeze_daytime = false - surface.solar_power_multiplier = 1 - surface.min_brightness = 0.15 - surface.brightness_visual_weights = {0, 0, 0, 1} - end, + on_world_start = function(journey) + local surface = game.surfaces.nauvis + surface.daytime = 0.44 + surface.freeze_daytime = true + surface.solar_power_multiplier = 3 + surface.min_brightness = 0 + surface.brightness_visual_weights = {0.8, 0.8, 0.8, 1} + end, + clear = function(journey) + local surface = game.surfaces.nauvis + surface.freeze_daytime = false + surface.solar_power_multiplier = 1 + surface.min_brightness = 0.15 + surface.brightness_visual_weights = {0, 0, 0, 1} + end, } Public.matter_anomaly = { - on_world_start = function(journey) - local force = game.forces.player - for i = 1, 4, 1 do force.technologies['mining-productivity-' .. i].researched = true end - for i = 1, 6, 1 do force.technologies['mining-productivity-4'].researched = true end - end, - on_robot_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "electric-turret" then entity.die() end - end, - on_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "electric-turret" then entity.die() end - end, + on_world_start = function(journey) + local force = game.forces.player + for i = 1, 4, 1 do force.technologies['mining-productivity-' .. i].researched = true end + for i = 1, 6, 1 do force.technologies['mining-productivity-4'].researched = true end + end, + on_robot_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'electric-turret' then entity.die() end + end, + on_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'electric-turret' then entity.die() end + end, } Public.quantum_anomaly = { - on_world_start = function(journey) - local force = game.forces.player - for i = 1, 6, 1 do force.technologies['research-speed-' .. i].researched = true end - game.difficulty_settings.technology_price_multiplier = game.difficulty_settings.technology_price_multiplier * 0.5 - end, - clear = function(journey) - game.difficulty_settings.technology_price_multiplier = game.difficulty_settings.technology_price_multiplier * 2 - end, + on_world_start = function(journey) + local force = game.forces.player + for i = 1, 6, 1 do force.technologies['research-speed-' .. i].researched = true end + journey.world_specials['technology_price_multiplier'] = 0.5 + end, } Public.mountainous = { - on_player_mined_entity = function(event) - local entity = event.entity - if not entity.valid then return end - if not rock_yield[entity.name] then return end - local surface = entity.surface - event.buffer.clear() - local ore = ore_raffle[math_random(1, size_of_ore_raffle)] - local count = math_floor(math_sqrt(entity.position.x ^ 2 + entity.position.y ^ 2) * 0.05) + math_random(25, 75) - local ore_amount = math_floor(count * 0.85) - local stone_amount = math_floor(count * 0.15) - surface.spill_item_stack(entity.position, {name = ore, count = ore_amount}, true) - surface.spill_item_stack(entity.position, {name = 'stone', count = stone_amount}, true) - end, - on_chunk_generated = function(event, journey) - local surface = event.surface - local seed = surface.map_gen_settings.seed - local left_top_x = event.area.left_top.x - local left_top_y = event.area.left_top.y - local get_tile = surface.get_tile - local position - local noise - for x = 0, 31, 1 do - for y = 0, 31, 1 do - if math_random(1, 3) ~= 1 then - position = {x = left_top_x + x, y = left_top_y + y} - if surface.can_place_entity({name = "coal", position = position}) then - noise = math_abs(Get_noise('scrapyard', position, seed)) - if noise < 0.025 or noise > 0.50 then - surface.create_entity({name = rock_raffle[math_random(1, size_of_rock_raffle)], position = position}) - end - end - end - end - end - end, + on_player_mined_entity = function(event) + local entity = event.entity + if not entity.valid then return end + if not rock_yield[entity.name] then return end + local surface = entity.surface + event.buffer.clear() + local ore = ore_raffle[math_random(1, size_of_ore_raffle)] + local count = math_floor(math_sqrt(entity.position.x ^ 2 + entity.position.y ^ 2) * 0.05) + math_random(25, 75) + local ore_amount = math_floor(count * 0.85) + local stone_amount = math_floor(count * 0.15) + surface.spill_item_stack(entity.position, {name = ore, count = ore_amount}, true) + surface.spill_item_stack(entity.position, {name = 'stone', count = stone_amount}, true) + end, + on_chunk_generated = function(event, journey) + local surface = event.surface + local seed = surface.map_gen_settings.seed + local left_top_x = event.area.left_top.x + local left_top_y = event.area.left_top.y + local position + local noise + for x = 0, 31, 1 do + for y = 0, 31, 1 do + if math_random(1, 3) ~= 1 then + position = {x = left_top_x + x, y = left_top_y + y} + if surface.can_place_entity({name = 'coal', position = position}) then + noise = math_abs(Get_noise('scrapyard', position, seed)) + if noise < 0.025 or noise > 0.50 then + surface.create_entity({name = rock_raffle[math_random(1, size_of_rock_raffle)], position = position}) + end + end + end + end + end + end, } Public.replicant_fauna = { - on_entity_died = function(event) - local entity = event.entity - if not entity.valid then return end - local cause = event.cause - if not cause then return end - if not cause.valid then return end - if cause.force.index == 2 then cause.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor), position = entity.position, force = "enemy"}) end - end, + on_entity_died = function(event) + local entity = event.entity + if not entity.valid then return end + local cause = event.cause + if not cause then return end + if not cause.valid then return end + if cause.force.index == 2 then cause.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor), position = entity.position, force = 'enemy'}) end + end, } -Public.tarball = { - on_robot_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "entity-ghost" or entity.type == "tile-ghost" or entity.type == "container" or entity.type == "wall" or entity.type == "pipe" then return end - entity.minable = false - end, - on_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "entity-ghost" or entity.type == "tile-ghost" or entity.type == "container" or entity.type == "wall" or entity.type == "pipe" then return end - entity.minable = false - end, - on_chunk_generated = function(event, journey) - table.insert(journey.world_color_filters, rendering.draw_sprite( - { - sprite = 'tile/lab-dark-1', - x_scale = 32, - y_scale = 32, - target = event.area.left_top, - surface = event.surface, - tint = {r = 0.0, g = 0.0, b = 0.0, a = 0.45}, - render_layer = 'ground' - } - )) - end, - clear = function(journey) - for _, id in pairs(journey.world_color_filters) do rendering.destroy(id) end - journey.world_color_filters = {} - end, +Public.tarball = { + on_robot_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'entity-ghost' or entity.type == 'tile-ghost' or entity.type == 'container' or entity.type == 'wall' or entity.type == 'pipe' then return end + entity.minable = false + end, + on_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'entity-ghost' or entity.type == 'tile-ghost' or entity.type == 'container' or entity.type == 'wall' or entity.type == 'pipe' then return end + entity.minable = false + end, + on_chunk_generated = function(event, journey) + table.insert(journey.world_color_filters, rendering.draw_sprite( + { + sprite = 'tile/lab-dark-1', + x_scale = 32, + y_scale = 32, + target = event.area.left_top, + surface = event.surface, + tint = {r = 0.0, g = 0.0, b = 0.0, a = 0.45}, + render_layer = 'ground' + } + )) +end, +clear = function(journey) + for _, id in pairs(journey.world_color_filters) do rendering.destroy(id) end + journey.world_color_filters = {} +end, } Public.swamps = { - on_chunk_generated = function(event, journey) - local surface = event.surface - local seed = surface.map_gen_settings.seed - local left_top_x = event.area.left_top.x - local left_top_y = event.area.left_top.y - - local tiles = {} - for _, tile in pairs(surface.find_tiles_filtered({name = {"water", "deepwater"}, area = event.area})) do - table.insert(tiles, {name = "water-shallow", position = tile.position}) - end - surface.set_tiles(tiles, true, false, false, false) - - local tiles = {} - for x = 0, 31, 1 do - for y = 0, 31, 1 do - local position = {x = left_top_x + x, y = left_top_y + y} - local noise = Get_noise('journey_swamps', position, seed) - if noise > 0.45 or noise < -0.65 then table.insert(tiles, {name = "water-shallow", position = {x = position.x, y = position.y}}) end - end - end - surface.set_tiles(tiles, true, false, false, false) - - for _, tile in pairs(tiles) do - if math_random(1, 32) == 1 then - surface.create_entity({name = "fish", position = tile.position}) - end - end - end, + on_world_start = function(journey) + journey.world_specials['water'] = 2 + end, + on_chunk_generated = function(event, journey) + local surface = event.surface + local seed = surface.map_gen_settings.seed + local left_top_x = event.area.left_top.x + local left_top_y = event.area.left_top.y + + local tiles = {} + for _, tile in pairs(surface.find_tiles_filtered({name = {'water', 'deepwater'}, area = event.area})) do + table.insert(tiles, {name = 'water-shallow', position = tile.position}) + end + + for x = 0, 31, 1 do + for y = 0, 31, 1 do + local position = {x = left_top_x + x, y = left_top_y + y} + local noise = Get_noise('journey_swamps', position, seed) + if noise > 0.45 or noise < -0.65 then table.insert(tiles, {name = 'water-shallow', position = {x = position.x, y = position.y}}) end + end + end + surface.set_tiles(tiles, true, false, false, false) + + for _, tile in pairs(tiles) do + if math_random(1, 32) == 1 then + surface.create_entity({name = 'fish', position = tile.position}) + end + end + end, } Public.wasteland = { - on_chunk_generated = function(event, journey) - local surface = event.surface - local seed = surface.map_gen_settings.seed - local left_top_x = event.area.left_top.x - local left_top_y = event.area.left_top.y - local tiles = {} - for _, tile in pairs(surface.find_tiles_filtered({name = {"water"}, area = event.area})) do - table.insert(tiles, {name = "water-green", position = tile.position}) - end - for _, tile in pairs(surface.find_tiles_filtered({name = {"deepwater"}, area = event.area})) do - table.insert(tiles, {name = "deepwater-green", position = tile.position}) - end - surface.set_tiles(tiles, true, false, false, false) - if math_random(1, 3) ~= 1 then return end - for _ = 1, math_random(0, 5), 1 do - local name = wrecks[math_random(1, size_of_wrecks)] - position = surface.find_non_colliding_position(name, {left_top_x + math_random(0, 31), left_top_y + math_random(0, 31)}, 16, 1) - if position then - local e = surface.create_entity({name = name, position = position, force = 'neutral'}) - if math_random(1, 4) == 1 then - local slots = game.entity_prototypes[e.name].get_inventory_size(defines.inventory.chest) - local blacklist = LootRaffle.get_tech_blacklist(0.2) - local item_stacks = LootRaffle.roll(math_random(16, 64), slots, blacklist) - for _, item_stack in pairs(item_stacks) do e.insert(item_stack) end - end - end - end - end, - on_world_start = function(journey) - local surface = game.surfaces.nauvis - local mgs = surface.map_gen_settings - mgs.terrain_segmentation = 2.7 - mgs.water = mgs.water + 1 - surface.map_gen_settings = mgs - surface.clear(true) - end, - clear = function(journey) - local surface = game.surfaces.nauvis - local mgs = surface.map_gen_settings - mgs.water = mgs.water - 1 - surface.map_gen_settings = mgs - end, + on_chunk_generated = function(event, journey) + local surface = event.surface + local left_top_x = event.area.left_top.x + local left_top_y = event.area.left_top.y + local tiles = {} + for _, tile in pairs(surface.find_tiles_filtered({name = {'water'}, area = event.area})) do + table.insert(tiles, {name = 'water-green', position = tile.position}) + end + for _, tile in pairs(surface.find_tiles_filtered({name = {'deepwater'}, area = event.area})) do + table.insert(tiles, {name = 'deepwater-green', position = tile.position}) + end + surface.set_tiles(tiles, true, false, false, false) + if math_random(1, 3) ~= 1 then return end + for _ = 1, math_random(0, 5), 1 do + local name = wrecks[math_random(1, size_of_wrecks)] + local position = surface.find_non_colliding_position(name, {left_top_x + math_random(0, 31), left_top_y + math_random(0, 31)}, 16, 1) + if position then + local e = surface.create_entity({name = name, position = position, force = 'neutral'}) + if math_random(1, 4) == 1 then + local slots = game.entity_prototypes[e.name].get_inventory_size(defines.inventory.chest) + local blacklist = LootRaffle.get_tech_blacklist(0.2) + local item_stacks = LootRaffle.roll(math_random(16, 64), slots, blacklist) + for _, item_stack in pairs(item_stacks) do e.insert(item_stack) end + end + end + end + end, + on_world_start = function(journey) + local surface = game.surfaces.nauvis + local mgs = surface.map_gen_settings + mgs.terrain_segmentation = 2.7 + mgs.water = mgs.water + 1 + surface.map_gen_settings = mgs + surface.clear(true) + end, + clear = function(journey) + local surface = game.surfaces.nauvis + local mgs = surface.map_gen_settings + mgs.water = mgs.water - 1 + surface.map_gen_settings = mgs + end, } Public.oceanic = { - on_world_start = function(journey) - local surface = game.surfaces.nauvis - local mgs = surface.map_gen_settings - mgs.terrain_segmentation = 0.5 - mgs.water = mgs.water + 4 - surface.map_gen_settings = mgs - surface.clear(true) - end, - on_robot_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "fluid-turret" then entity.die() end - end, - on_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "fluid-turret" then entity.die() end - end, - clear = function(journey) - local surface = game.surfaces.nauvis - local mgs = surface.map_gen_settings - mgs.water = mgs.water - 4 - surface.map_gen_settings = mgs - end, + on_world_start = function(journey) + local surface = game.surfaces.nauvis + local mgs = surface.map_gen_settings + mgs.terrain_segmentation = 0.5 + mgs.water = mgs.water + 6 + surface.map_gen_settings = mgs + surface.clear(true) + end, + on_robot_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'fluid-turret' then entity.die() end + end, + on_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'fluid-turret' then entity.die() end + end, + clear = function(journey) + local surface = game.surfaces.nauvis + local mgs = surface.map_gen_settings + mgs.water = mgs.water - 6 + surface.map_gen_settings = mgs + end, } Public.volcanic = { - on_chunk_generated = function(event, journey) - table.insert(journey.world_color_filters, rendering.draw_sprite({ - sprite = 'tile/lab-dark-2', - x_scale = 32, - y_scale = 32, - target = event.area.left_top, - surface = event.surface, - tint = {r = 0.55, g = 0.0, b = 0.0, a = 0.25}, - render_layer = 'ground' - })) - end, - on_player_changed_position = function(event) - local player = game.players[event.player_index] - if player.driving then return end - local surface = player.surface - if surface.index ~= 1 then return end - if solid_tiles[surface.get_tile(player.position).name] then return end - surface.create_entity({name = "fire-flame", position = player.position}) - end, - on_world_start = function(journey) - local surface = game.surfaces.nauvis - surface.request_to_generate_chunks({x = 0, y = 0}, 3) - surface.force_generate_chunk_requests() - surface.spill_item_stack({0, 0}, {name = "stone-brick", count = 4096}, true) - for x = -24, 24, 1 do - for y = -24, 24, 1 do - if math.sqrt(x ^ 2 + y ^ 2) < 24 then - surface.set_tiles({{name = "stone-path", position = {x, y}}}, true) - end - end - end - end, - clear = function(journey) - for _, id in pairs(journey.world_color_filters) do rendering.destroy(id) end - journey.world_color_filters = {} - end, + on_chunk_generated = function(event, journey) + table.insert(journey.world_color_filters, rendering.draw_sprite({ + sprite = 'tile/lab-dark-2', + x_scale = 32, + y_scale = 32, + target = event.area.left_top, + surface = event.surface, + tint = {r = 0.55, g = 0.0, b = 0.0, a = 0.25}, + render_layer = 'ground' + })) + end, + on_player_changed_position = function(event) + local player = game.players[event.player_index] + if player.driving then return end + local surface = player.surface + if surface.index ~= 1 then return end + if solid_tiles[surface.get_tile(player.position).name] then return end + surface.create_entity({name = 'fire-flame', position = player.position}) + end, + on_world_start = function(journey) + local surface = game.surfaces.nauvis + surface.request_to_generate_chunks({x = 0, y = 0}, 3) + surface.force_generate_chunk_requests() + surface.spill_item_stack({0, 0}, {name = 'stone-brick', count = 4096}, true) + for x = -24, 24, 1 do + for y = -24, 24, 1 do + if math.sqrt(x ^ 2 + y ^ 2) < 24 then + surface.set_tiles({{name = 'stone-path', position = {x, y}}}, true) + end + end + end + end, + clear = function(journey) + for _, id in pairs(journey.world_color_filters) do rendering.destroy(id) end + journey.world_color_filters = {} + end, } Public.chaotic_resources = { - on_chunk_generated = function(event, journey) - local surface = event.surface - for _, ore in pairs(surface.find_entities_filtered({area = event.area, name = {'iron-ore', 'copper-ore', 'coal', 'stone'}})) do - surface.create_entity({name = ore_raffle_2[math_random(1, size_of_ore_raffle_2)], position = ore.position, amount = ore.amount}) - ore.destroy() - end - end, + on_chunk_generated = function(event, journey) + local surface = event.surface + for _, ore in pairs(surface.find_entities_filtered({area = event.area, name = {'iron-ore', 'copper-ore', 'coal', 'stone'}})) do + surface.create_entity({name = ore_raffle_2[math_random(1, size_of_ore_raffle_2)], position = ore.position, amount = ore.amount}) + ore.destroy() + end + end, } Public.infested = { - on_entity_died = function(event) - local entity = event.entity - if not entity.valid then return end - if entity.force.index ~= 3 then return end - if entity.type ~= "simple-entity" and entity.type ~= "tree" then return end - entity.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor + 0.1), position = entity.position, force = 'enemy'}) - end, - on_player_mined_entity = function(event) - local entity = event.entity - if not entity.valid then return end - if entity.force.index ~= 3 then return end - if entity.type ~= "simple-entity" and entity.type ~= "tree" then return end - entity.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor + 0.1), position = entity.position, force = 'enemy'}) - end, - on_robot_mined_entity = function(event) - local entity = event.entity - if not entity.valid then return end - if entity.force.index ~= 3 then return end - if entity.type ~= "simple-entity" and entity.type ~= "tree" then return end - entity.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor + 0.1), position = entity.position, force = 'enemy'}) - end, + on_chunk_generated = function(event, journey) + table.insert(journey.world_color_filters, rendering.draw_sprite({ + sprite = 'tile/lab-dark-2', + x_scale = 32, + y_scale = 32, + target = event.area.left_top, + surface = event.surface, + tint = {r = 0.8, g = 0.0, b = 0.8, a = 0.25}, + render_layer = 'ground' + })) + end, + on_world_start = function(journey) + journey.world_specials['trees_size'] = 4 + journey.world_specials['trees_richness'] = 2 + journey.world_specials['trees_frequency'] = 2 + end, + clear = function(journey) + for _, id in pairs(journey.world_color_filters) do rendering.destroy(id) end + journey.world_color_filters = {} + end, + on_entity_died = function(event) + local entity = event.entity + if not entity.valid then return end + if entity.force.index ~= 3 then return end + if entity.type ~= 'simple-entity' and entity.type ~= 'tree' then return end + entity.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor + 0.1), position = entity.position, force = 'enemy'}) + end, + on_player_mined_entity = function(event) + if math_random(1,2) == 1 then return end + local entity = event.entity + if not entity.valid then return end + if entity.force.index ~= 3 then return end + if entity.type ~= 'simple-entity' and entity.type ~= 'tree' then return end + entity.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor + 0.1), position = entity.position, force = 'enemy'}) + end, + on_robot_mined_entity = function(event) + local entity = event.entity + if not entity.valid then return end + if entity.force.index ~= 3 then return end + if entity.type ~= 'simple-entity' and entity.type ~= 'tree' then return end + entity.surface.create_entity({name = BiterRaffle.roll('mixed', game.forces.enemy.evolution_factor + 0.1), position = entity.position, force = 'enemy'}) + end, } Public.undead_plague = { - on_entity_died = function(event) - local entity = event.entity - if not entity.valid then return end - if entity.force.index ~= 2 then return end - if math_random(1,2) == 1 then return end - if entity.type ~= "unit" then return end - entity.surface.create_entity({name = entity.name, position = entity.position, force = 'enemy'}) - end, + on_entity_died = function(event) + local entity = event.entity + if not entity.valid then return end + if entity.force.index ~= 2 then return end + if math_random(1,2) == 1 then return end + if entity.type ~= 'unit' then return end + entity.surface.create_entity({name = entity.name, position = entity.position, force = 'enemy'}) + end, } Public.low_mass = { - on_world_start = function(journey) - local force = game.forces.player - force.character_running_speed_modifier = 0.5 - for i = 1, 6, 1 do force.technologies['worker-robots-speed-' .. i].researched = true end - end, + on_world_start = function(journey) + local force = game.forces.player + force.character_running_speed_modifier = 0.5 + for i = 1, 6, 1 do force.technologies['worker-robots-speed-' .. i].researched = true end + end, } Public.dense_atmosphere = { - on_robot_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "roboport" then entity.die() end - end, - on_built_entity = function(event) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "roboport" then entity.die() end - end, + on_robot_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'roboport' then entity.die() end + end, + on_built_entity = function(event) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'roboport' then entity.die() end + end, } local function update_lazy_bastard(journey, count) - journey.lazy_bastard_machines = journey.lazy_bastard_machines + count - local speed = journey.lazy_bastard_machines * -0.1 - if speed < -1 then speed = -1 end - game.forces.player.manual_crafting_speed_modifier = speed + journey.lazy_bastard_machines = journey.lazy_bastard_machines + count + local speed = journey.lazy_bastard_machines * -0.1 + if speed < -1 then speed = -1 end + game.forces.player.manual_crafting_speed_modifier = speed end Public.lazy_bastard = { - on_robot_built_entity = function(event, journey) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "assembling-machine" then - update_lazy_bastard(journey, 1) - end - end, - on_built_entity = function(event, journey) - local entity = event.created_entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "assembling-machine" then - update_lazy_bastard(journey, 1) - end - end, - on_entity_died = function(event, journey) - local entity = event.entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "assembling-machine" then - update_lazy_bastard(journey, -1) - end - end, - on_player_mined_entity = function(event, journey) - local entity = event.entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "assembling-machine" then - update_lazy_bastard(journey, -1) - end - end, - on_robot_mined_entity = function(event, journey) - local entity = event.entity - if not entity.valid then return end - if entity.surface.index ~= 1 then return end - if entity.type == "assembling-machine" then - update_lazy_bastard(journey, -1) - end - end, - on_world_start = function(journey) - journey.lazy_bastard_machines = 0 - end, - clear = function(journey) - game.forces.player.manual_crafting_speed_modifier = 0 - end, + on_robot_built_entity = function(event, journey) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'assembling-machine' then + update_lazy_bastard(journey, 1) + end + end, + on_built_entity = function(event, journey) + local entity = event.created_entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'assembling-machine' then + update_lazy_bastard(journey, 1) + end + end, + on_entity_died = function(event, journey) + local entity = event.entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'assembling-machine' then + update_lazy_bastard(journey, -1) + end + end, + on_player_mined_entity = function(event, journey) + local entity = event.entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'assembling-machine' then + update_lazy_bastard(journey, -1) + end + end, + on_robot_mined_entity = function(event, journey) + local entity = event.entity + if not entity.valid then return end + if entity.surface.index ~= 1 then return end + if entity.type == 'assembling-machine' then + update_lazy_bastard(journey, -1) + end + end, + on_world_start = function(journey) + journey.lazy_bastard_machines = 0 + end, + clear = function(journey) + game.forces.player.manual_crafting_speed_modifier = 0 + end, } Public.ribbon = { - on_world_start = function(journey) - local surface = game.surfaces.nauvis - local mgs = surface.map_gen_settings - mgs.height = 256 - surface.map_gen_settings = mgs - surface.clear(true) - end, - clear = function(journey) - local surface = game.surfaces.nauvis - local mgs = surface.map_gen_settings - mgs.height = nil - surface.map_gen_settings = mgs - end, + on_chunk_generated = function(event, journey) + local surface = event.surface + local left_top_x = event.area.left_top.x + local left_top_y = event.area.left_top.y + if (left_top_x + left_top_y)^2 <= 256 then + local oils = surface.count_entities_filtered{name = 'crude-oil', position = {x = 0,y =0}, radius = 256} + if math.random(1, 10 + oils * 10) == 1 then + local pos = surface.find_non_colliding_position_in_box('oil-refinery', event.area, 0.1, true) + if pos then + surface.create_entity({name = 'crude-oil', position = pos, amount = 60000}) + end + end + end + end, + on_world_start = function(journey) + local surface = game.surfaces.nauvis + local mgs = surface.map_gen_settings + mgs.height = 256 + surface.map_gen_settings = mgs + surface.clear(true) + end, + clear = function(journey) + local surface = game.surfaces.nauvis + local mgs = surface.map_gen_settings + mgs.height = nil + surface.map_gen_settings = mgs + end, } Public.abandoned_library = { - on_world_start = function(journey) - game.permissions.get_group('Default').set_allows_action(defines.input_action.open_blueprint_library_gui, false) - game.permissions.get_group('Default').set_allows_action(defines.input_action.import_blueprint_string, false) - end, - clear = function(journey) - game.permissions.get_group('Default').set_allows_action(defines.input_action.open_blueprint_library_gui, true) - game.permissions.get_group('Default').set_allows_action(defines.input_action.import_blueprint_string, true) - end, + on_world_start = function(journey) + game.permissions.get_group('Default').set_allows_action(defines.input_action.open_blueprint_library_gui, false) + game.permissions.get_group('Default').set_allows_action(defines.input_action.import_blueprint_string, false) + end, + clear = function(journey) + game.permissions.get_group('Default').set_allows_action(defines.input_action.open_blueprint_library_gui, true) + game.permissions.get_group('Default').set_allows_action(defines.input_action.import_blueprint_string, true) + end, } -return Public \ No newline at end of file +Public.railworld = { + on_world_start = function(journey) + journey.world_specials['ore_size'] = 4 + journey.world_specials['ore_frequency'] = 0.25 + journey.world_specials['coal'] = 4 + journey.world_specials['stone'] = 4 + journey.world_specials['copper-ore'] = 4 + journey.world_specials['iron-ore'] = 4 + journey.world_specials['uranium-ore'] = 4 + journey.world_specials['crude-oil'] = 4 + journey.world_specials['enemy_base_frequency'] = 0.25 + journey.world_specials['enemy_base_size'] = 2 + journey.world_specials['enemy_base_richness'] = 2 + journey.world_specials['water'] = 1.5 + journey.world_specials['starting_area'] = 3 + end, +} + +local delivery_options = { + 'solar-panel', + 'rocket-part', + 'beacon', + 'assembling-machine-3', + 'low-density-structure', + 'heat-pipe', + 'express-transport-belt', + 'logistic-robot', + 'power-armor' +} + +Public.resupply_station = { + on_world_start = function(journey) + local pick = delivery_options[math.random(1, #delivery_options)] + journey.speedrun = {enabled = true, time = 0, item = pick} + journey.mothership_cargo_space[pick] = game.item_prototypes[pick].stack_size + end, + clear = function(journey) + journey.mothership_cargo_space[journey.speedrun.item] = nil + journey.mothership_cargo[journey.speedrun.item] = 0 + journey.speedrun.enabled = false + end, +} + +return Public