diff --git a/functions/soft_reset.lua b/functions/soft_reset.lua index eb08eb2a..492c362e 100644 --- a/functions/soft_reset.lua +++ b/functions/soft_reset.lua @@ -7,6 +7,9 @@ local function reset_forces(new_surface, old_surface) for _, f in pairs(game.forces) do local spawn = {x = game.forces.player.get_spawn_position(old_surface).x, y = game.forces.player.get_spawn_position(old_surface).y} f.reset() + for _, tech in pairs(f.technologies) do + f.set_saved_technology_progress(tech, 0) + end f.reset_evolution() f.set_spawn_position(spawn, new_surface) end diff --git a/locale/en/locale.cfg b/locale/en/locale.cfg index 6987dc90..fd7ee64f 100644 --- a/locale/en/locale.cfg +++ b/locale/en/locale.cfg @@ -65,38 +65,44 @@ map_info_sub_caption= ..diggy diggy choo choo.. map_info_text=The biters have catched the scent of fish in the cargo wagon.\nGuide the choo into the mountain and protect it as long as possible!\nThis however will not be an easy task,\nsince their strength and numbers increase over time.\n\nIn additon, the southern grounds collapse over time.\n\nDelve deep for greater treasures, but also face increased dangers.\nMining productivity research, will overhaul your mining equipment,\nreinforcing your pickaxe as well as increasing the size of your backpack.\n\nAs you dig, you will encounter impassable dark chasms or rivers.\nSome explosives may cause parts of the ceiling to crumble, filling the void, creating new ways.\nAll they need is a container and a well aimed shot.\n\nYou may find some supply goods, if you enter the wagon.\nGood luck on your journey! [chronosphere] -map_info_main_caption=Chronosphere +map_info_main_caption=C H R O N O S P H E R E map_info_sub_caption= ..Comfylatron gone wild.. -map_info_text_old=Comfylatron has seized The Fish Train and turned it into a time machine.\nIt is your job to make sure the cargo is safe throughout the times and places we travel through!\nThis however will not be an easy task,\nas Comfylatron does not have any idea how to control this machine at all.\n\nThe destinations of quantum time jumps are completely random, and the machine always needs time to recharge.\nYou can speed it up greatly by charging acumulators in Locomotive.\nSo be sure to grab as many resources as you can before the train jump away!\nComfylatron manages to run teleporting devices to transport items into train from his chests. Also to save people from staying in wrong universe.\n\nOnce a quantum jump is initiated, be sure to have everything packed up, there is nearly zero chance to revisit that place again!\nMining productivity research will overhaul your mining equipment,\nreinforcing your pickaxes, as well as increasing the size of your backpack.\nGood luck on your journey! -map_info_text=Comfylatron has seized the Fish Train and turned it into a time machine.\n Your job as his slave is:\n\n[1] Keep train alive at all costs\n[2] Gather resources while travelling through different maps.\n[3a] Press enter on cargo wagons to enter insides of train.\n[3b] Press enter on cars to exit the train.\n[4] Charging acumulators inside train speeds up jumps when leaving early is needed.\nCharging and jumping creates huge pollution so be ready to get attacked.\n[5] Items inserted into comfylatron chests get teleported into train.\n[6] Some planets are poor, some are rich, and some are just too dangerous.\n\n Loot, but also evolution grows with jumps performed.\n During jump, personnel will be teleported in,\n however dead bodies nor buildings won't.\nMining productivity grants inventory space and handmining speed.\n\nGood luck. Don't let biters ruin the show! -planet_jump=Destination: __1__, Ore Richness: __2__, Daynight cycle: __3__ -message_danger1=Comfylatron: We have a problem! We got disrupted in mid-jump, only part of energy got used, and here we landed. It might have been a trap! -message_danger2=Comfylatron: My analysis says that charging needs full energy reset to work again, so we are stuck there until next full jump. -message_danger3=Robot voice: INTRUDER ALERT! Lifeforms detected! Must eliminate! -message_danger4=Robot voice: Nuclear missiles armed, launch countdown enabled. -message_jump180=Comfylatron: Acumulator charging disabled, 180 seconds countdown to jump! -message_jump60=Comfylatron: ChronoTrain nearly charged! Grab what you can, we leaving in 60 seconds! -message_jump30=Comfylatron: You better hurry up! 30 seconds remaining! -message_nuke=Warning: Nuclear missiles launched. -message_accident=Comfylatron: Offline player had an accident, and dropped his items on ground around locomotive. -message_silo=Nuclear silo destroyed. You managed to loot 5 atomic bombs. Comfylatron seized them for your own safety. -message_game_won_restart=Comfylatron: WAIT whaat? Looks like we did not fixed the train properly and it teleported us back in time...sigh...so let's do this again, and now properly. -message_fishmarket1=Comfylatron: So here we are. Fish Market. When they ordered the fish, they said this location is perfectly safe. Looks like we will have to do it for them. -message_fishmarket2=Comfylatron: I hope you have enough nukes. Also, that satellite gave us some space knowledge. -message_fishmarket3=Comfylatron: Luckily we looted some nukes before, take them. -message_lava=Comfylatron: OOF this one is a bit hot. And have seen those biters? They BATHE in fire! Maybe try some bricks to protect from lava? -message_choppy=Comfylatron: OwO what are those strange trees?!? They have ore fruits! WTF! -message_game_lost1=The chronotrain was destroyed! -message_game_lost2=Comfylatron is going to kill you for that...he has time machine after all! -message_evolve=Comfylatron: Biters start to evolve faster! We need to charge forward or they will be stronger! (hover over timer to see evolve timer) -message_quest1=Comfylatron: You know...I have big quest. Deliver fish to fish market. But this train is broken. Please help me fix the train computer! -message_quest3=Comfylatron: Ah, we need to give this machine more power and better navigation chipset. Please bring me some additional things. -message_quest5=Comfylatron: Finally found the main issue. We will need to rebuild whole processor. Exactly what I feared of. Just a few more things... -message_quest6=Comfylatron: And this was last part of cpu brain done. Now we just need to synchronize our time correctly and we are done! Bring me satellite and rocket silo. -message_quest7=Comfylatron: Time synchronized. Calculating time and space destination. Success. Jump once more and let me deliver the fish finally. This trip is getting long. -message_game_won1=Comfylatron: Thank you with helping me on this delivery. It was tough one. I hope, that now, when all biters are dead, fish will be safe here forever... -message_overstay=Comfylatron: Looks like you stayed on previous planet for so long that enemies on other planets had additional time to evolve! +map_info_text_old=Comfylatron has seized the Fish Train and turned it into a time machine.\n Your job as his slave is:\n\n[1] Keep train alive at all costs\n[2] Gather resources while travelling through different maps.\n[3a] Press enter on cargo wagons to enter insides of train.\n[3b] Press enter on cars to exit the train.\n[4] Charging acumulators inside train speeds up jumps when leaving early is needed.\nCharging and jumping creates huge pollution so be ready to get attacked.\n[5] Items inserted into comfylatron chests get teleported into train.\n[6] Some planets are poor, some are rich, and some are just too dangerous.\n\n Loot, but also evolution grows with jumps performed.\n During jump, personnel will be teleported in,\n however dead bodies nor buildings won't.\nMining productivity grants inventory space and handmining speed.\n\nGood luck. Don't let biters ruin the show! + +map_info_text=Comfylatron has seized the Fish Train and turned it into a time machine.\n Your job as his slave is:\n\n[1] Keep train alive at all costs.\n[2] Gather resources while travelling through different planets.\n[3a] Press enter on cargo wagons to enter the insides of train.\n[3b] Press enter on cars to exit the Chronotrain.\n[4] Charging the accumulators inside the Chronotrain speeds up the jump, but creates HUGE pollution, aggravating the biters.\n[5] Items inserted into the Chronotrain chests get teleported into the train.\n[6] Some planets are poor, some are rich, and some are just too dangerous.\n\nLoot, but also evolution, grows with jumps performed.\n During jump, personnel and their inventories will be teleported in, but anything left behind outside won't.\nEarly jumps award 25 coins per minute spared (until the 25th jump).\nObtaining mining productivity research grants inventory space and hand-mining speed.\n\nGood luck. Don't let biters ruin the show! +planet_jump=Destination: __1__, Ore richness: __2__, Day length: __3__ + +message_danger1=Comfylatron: The chronojump misfired! Hang on a second! +message_danger2=Comfylatron: Oo-ee! That's worse than I thought, our chronojump went sideways.. +message_danger3=Robot voice: INTRUDER ALERT! Lifeforms detected!! Must eliminate!! +message_danger4=Comfylatron: Welp. The charger is shot. We'll have to wait. +message_danger5=Robot voice: Nuclear missiles armed. Launch countdown enabled. +message_rampup50=Comfylatron: The biters are making me nervous... =owo= +message_overstay=Comfylatron: We took so long to get off that planet, our future destinations have evolved a little... +message_initiate_jump_countdown=Comfylatron: OK, firing her up!! Looks like __1__ seconds 'till jump! +message_jump60=Comfylatron: Nearly there! Grab what you can, we're leaving in 60 seconds! +message_jump30=Comfylatron: You'd better hurry up! 30 seconds remaining!! +message_jump_10orless=Comfylatron: Jump in __1__ seconds! +message_jump_misfire=Comfylatron: The chronojump misfired! Hang on a second! message_poison_defense=Comfylatron: Triggering poison defense. Let's kill everything! +message_nuke=Warning: Nuclear missiles launched. +message_accident=Comfylatron: Offline player had an accident, and their corpse fell to the ground near the locomotive. +message_silo=Nuclear silo destroyed. You looted __1__ atomic bombs. Comfylatron seized them for your own safety. +message_game_won_restart=Comfylatron: WHOOSH... the chronotrain teleported us back in time... so let's do this again... +message_fishmarket1=Comfylatron: So here we are. Fish Market. When they ordered the fish, they told us this location was safe. Guess we'll have to make it so. +message_fishmarket2=Comfylatron: I hope you have enough nukes. That satellite gave us some space knowledge! +message_fishmarket3=Comfylatron: Hey I found these nukes we looted before... you can take them. +message_lava=Comfylatron: OOF this one is a bit hot. Better keep your distance! Or try some bricks to protect from lava? And have seen those biters? They BATHE in fire! +message_choppy=Comfylatron: OwO what are those strange trees?!? They have ore fruits! WTF! +message_game_lost1=The Chronotrain was destroyed! +message_game_lost2=Comfylatron is going to kill you for that... he has a time machine after all! +message_evolve=Comfylatron: From this planet onwards, if we take too long to jump, the biters on future planets will evolve! +message_quest1=Comfylatron: Comfylatron has...a big quest!! The train is broken. Can you help me fix the train computer? And also bring fish to the fish market. +message_quest3=Comfylatron: Tch... More power... Better navigation chipset... they're so demanding. Are you engineers okay to get all that stuff? +message_quest5=Comfylatron: I was doing it wrong the whole time!!! I finally found the problem. We need to rebuild whole processor. Exactly what I feared of. Can you bring me a few more things? +message_quest6=Comfylatron: And, I've got the last part of the CPU brain done. Phew! Now we just need to synchronize our time correctly and we can get fish on the road! All I need is a satellite and a rocket silo ;) +message_quest7=Comfylatron: TIME SYNCHRONIZED... CALCULATING SPACETIME DESTINATION... Done! Power up the chrono engines for a warp into the pocket universe, whilst the fish after still alive!!!! +message_game_won1=Comfylatron: Thank you all, for helping me with fish delivery. It was tough ride. Let's hope they leave a good review. And now that the biters are dead, the fish will be safe here forever... map_1=Terra Ferrata map_2=Malachite Hills @@ -126,76 +132,82 @@ ore_richness_none=None daynight_static=Static daynight_normal=Normal daynight_slow=Slow -daynight_superslow=Super Slow +daynight_superslow=Super slow daynight_fast=Fast -daynight_superfast=Super Fast +daynight_superfast=Super fast upgrade_train_armor=Train Armor -upgrade_train_armor_message=Comfylatron: Train's max HP was upgraded. +upgrade_train_armor_message=Comfylatron: Chronotrain's max HP upgraded. upgrade_train_armor_tooltip=+2500 Train Max HP. Max level: __1__ Current Max HP: __2__ upgrade_filter=Pollution Filter -upgrade_filter_message=Comfylatron: Train's pollution filter was upgraded. -upgrade_filter_tooltip=Train Pollution Filter. Decreases pollution from inside of train and from chrono engine.\nCurrent pollution made by train: __1__% +upgrade_filter_message=Comfylatron: Chronotrain's pollution filter upgraded. +upgrade_filter_tooltip=Train Pollution Filter. Dampens pollution from machines inside the train and from charging the chrono engine.\nCurrent machine pollution transfer factor: __1__% upgrade_accumulators=Accumulators -upgrade_accumulators_message=Comfylatron: Train's accumulator capacity was upgraded. -upgrade_accumulators_tooltip=Add additional row of Accumulators for train's charging system.\nEach accumulator adds 300kW possible power input. +upgrade_accumulators_message=Comfylatron: Chronotrain's accumulator capacity upgraded. +upgrade_accumulators_tooltip=Add an additional row of accumulators to the Chronotrain, increasing the maximum power the chrono engine can draw. upgrade_loot_pickup=Loot Pickup Range -upgrade_loot_pickup_message=Comfylatron: Players now have additional red inserter installed on shoulders, increasing their item pickup range. +upgrade_loot_pickup_message=Comfylatron: Players install additional red inserters on their shoulders. Item pickup range increased. upgrade_loot_pickup_tooltip=Add loot pickup distance to players. Current: +__1__ tiles range upgrade_inventory_size=Character Inventory Size -upgrade_inventory_size_message=Comfylatron: Players now can carry more trash in their unsorted inventories. +upgrade_inventory_size_message=Comfylatron: Players can now carry more trash in their unsorted inventories. Just what we needed uwu upgrade_inventory_size_tooltip=Add +10 inventory slots to all players. upgrade_repair=Train Repair Speed -upgrade_repair_message=Comfylatron: Train now gets repaired with additional repair kit at once. -upgrade_repair_tooltip=Train uses more repair tools at once from Repair chest. Current: +__1__ +upgrade_repair_message=Comfylatron: The Chronotrain can now repair with an additional repair kit at once. +upgrade_repair_tooltip=The Chronotrain uses more repair tools at once from the Repair Chest. Current: +__1__ upgrade_water=Piping System -upgrade_water_message=Comfylatron: Train now has piping system for additional water sources. +upgrade_water_message=Comfylatron: The Chronotrain now has a piping system for additional water sources in each wagon. Am I allowed in the pool party?? upgrade_water_tooltip=Add piping through wagon sides to create water sources for each wagon. upgrade_output=Output System -upgrade_output_message=Comfylatron: Train now has output chests. -upgrade_output_tooltip=Add comfylatron chests that output outside (into cargo wagon 2 and 3) +upgrade_output_message=Comfylatron: The Chronotrain has been upgraded with output chests. Now it goes both ways! +upgrade_output_tooltip=Adds output chests to wagons 2 and 3 which send items to the external wagon storage. upgrade_storage=Train Storage -upgrade_storage_message=Comfylatron: Cargo wagons now have upgraded storage. -upgrade_storage_tooltip=Add and upgrade storage chests to the sides of wagons. +upgrade_storage_message=Comfylatron: Come look, the inside of the Chronotrain has upgraded storage. +upgrade_storage_tooltip=Add or upgrade storage chests to line the edges of the insides of the Chronotrain. upgrade_poison=Poison Defense -upgrade_poison_message=Comfylatron: I don't believe in your defense skills. I equipped train with poison defense. -upgrade_poison_tooltip=Poison defense. Triggers automatically when train has low HP.\nMax charges : 4. Recharge timer for next use: __1__ min. +upgrade_poison_message=Comfylatron: I don't believe in your defensive skills. I loaded another emergency poison defense into the locomotive... +upgrade_poison_tooltip=Emergency poison defense. Triggers automatically when the Chronotrain has low HP.\nMax charges : 4. Recharge timer for next use: __1__ min. upgrade_fusion=Fusion Reactor upgrade_fusion_message=Comfylatron: One personal fusion reactor ready. upgrade_fusion_tooltip=Creates one Fusion Reactor. upgrade_mk2=Power Armor MK2 -upgrade_mk2_message=Comfylatron: I upgraded one armor to mk2. +upgrade_mk2_message=Comfylatron: I upgraded an armor to MK2. upgrade_mk2_tooltip=Creates one Power Armor MK2 upgrade_computer1=Comfylatron's Quest 1 -upgrade_computer1_message=Comfylatron: Thanks for fixing train navigation. I can now get us rid of very poor worlds. It will still need more work though, come back after jump. -upgrade_computer1_tooltip=Progresses main quest.\nAll next worlds won't have "very poor" ore distribution. +upgrade_computer1_tooltip=Progresses main quest.\nNew planets won't ever have "very poor" ore distribution. +upgrade_computer1_message=Comfylatron: OK, now I can fix the train navigation... This should get rid of very poor worlds at least. It still needs more work, though. I'll tell you after the jump. upgrade_computer2=Comfylatron's Quest 2 -upgrade_computer2_message=Comfylatron: Perfect! Now we have train reactor and even better destination precision. I will get to you after jump with what still needs to be done. -upgrade_computer2_tooltip=Progresses main quest.\nAll next worlds won't have "poor" ore distribution. +upgrade_computer2_message=Comfylatron: Perfect! Now we have train reactor, and happily for you all, we should be able to avoid poor worlds altogether! Find out what's next after the jump ;) +upgrade_computer2_tooltip=Progresses main quest.\nNew planets won't ever have "poor" ore distribution. upgrade_computer3=Comfylatron's Quest 3 upgrade_computer3_message=Comfylatron: That's __1__ / 10 processor parts done! upgrade_computer3_tooltip=Progresses main quest.\nAfter completing 10th part, the final map can be unlocked. upgrade_computer4=Comfylatron's Final Quest -upgrade_computer4_message=Comfylatron: Time synchronized. Calculating time and space destination. Success. Jump once more and let me deliver the fish finally. This trip is getting long. -upgrade_computer4_tooltip=Progresses main quest.\nBy unlocking this, the next destination is Fish Market map.\nBe sure to be ready, there is no way back! +upgrade_computer4_message=Comfylatron: TIME SYNCHRONIZED... CALCULATING SPACETIME DESTINATION... Voila. Power up the chrono engines for a warp into the pocket universe!!!! +upgrade_computer4_tooltip=Progresses main quest.\nBy unlocking this, the next destination is Fish Market planet.\nBe sure to be ready... there's no way back! gui_1=ChronoJumps: gui_2=Charge: -gui_3=Timer: -gui_3_1=Best Case Timer: +gui_3=Expt. Charged: +gui_3_1=Best Case: gui_3_2=Nuclear missiles launched in: +gui_3_3=JUMP IN: gui_4=Local Evolution: -gui_planet_button=Map Info +gui_planet_button=Planet Info gui_upgrades_button=Upgrades -gui_upgrades_1=Insert needed items into chest with given picture. -gui_upgrades_2=Chests are at top inside the train. Upgrading can take a minute. +gui_upgrades_1=Purchase upgrades by placing items in the chests at the top of the train interior. +gui_upgrades_2=Upgrading can take a few seconds. gui_planet_0=Name: __1__ gui_planet_1=Detected ore distribution: gui_planet_2=Ore Amounts: __1__ gui_planet_3=Local evolution: __1__% gui_planet_4=Global evolution bonuses: gui_planet_4_1=+__1__% evolution, +__2__% damage -gui_planet_5=Daynight cycle: __1__ +gui_planet_5=Day/night cycle: __1__ +gui_planet_6=Overstay in: __1__ min, __2__s +gui_planet_7=Overstay applies after jump __1__ +gui_overstayed=Overstayed! +gui_not_overstayed=Avoided overstay. + [rocks_yield_ore_veins] coal=coal @@ -236,7 +248,7 @@ angels-ore6=umber gui_1=First wave in gui_2=Wave: gui_3=Threat: -tooltip_1=High threat empowers biters, worms and spawners.\nBiter health: __1__% +tooltip_1=High threat may empower biters.\nBiter health: __1__% tooltip_2=gain / minute [native_war] diff --git a/maps/chronosphere/ai.lua b/maps/chronosphere/ai.lua index 86604d4f..2dcddcaf 100644 --- a/maps/chronosphere/ai.lua +++ b/maps/chronosphere/ai.lua @@ -1,5 +1,7 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' local Difficulty = require 'modules.difficulty_vote' +local Rand = require 'maps.chronosphere.random' local Public = {} local math_random = math.random @@ -8,496 +10,481 @@ local math_floor = math.floor local worm_raffle = {'small-worm-turret', 'medium-worm-turret', 'big-worm-turret', 'behemoth-worm-turret'} local spawner_raffle = {'biter-spawner', 'biter-spawner', 'biter-spawner', 'spitter-spawner'} local biter_raffle = { - 'behemoth-biter', - 'behemoth-spitter', - 'big-biter', - 'big-spitter', - 'medium-biter', - 'medium-spitter', - 'small-biter', - 'small-spitter' + 'behemoth-biter', + 'behemoth-spitter', + 'big-biter', + 'big-spitter', + 'medium-biter', + 'medium-spitter', + 'small-biter', + 'small-spitter' } local vector_radius = 480 local attack_vectors = {} for x = vector_radius * -1, vector_radius, 1 do - for y = 0, vector_radius, 1 do - local r = math_sqrt(x ^ 2 + y ^ 2) - if r < vector_radius and r > vector_radius - 1 then - attack_vectors[#attack_vectors + 1] = {x, y} - end - end + for y = 0, vector_radius, 1 do + local r = math_sqrt(x ^ 2 + y ^ 2) + if r < vector_radius and r > vector_radius - 1 then + attack_vectors[#attack_vectors + 1] = {x, y} + end + end end local size_of_vectors = #attack_vectors local function get_active_biter_count() - local objective = Chrono_table.get_table() - local count = 0 - for k, _ in pairs(objective.active_biters) do - count = count + 1 - end - return count + local objective = Chrono_table.get_table() + local count = 0 + for k, _ in pairs(objective.active_biters) do + count = count + 1 + end + return count end local function set_biter_raffle_table(surface) - local objective = Chrono_table.get_table() - -- It's fine to only sample the middle - local area = {left_top = {-400, -400}, right_bottom = {400, 400}} + local objective = Chrono_table.get_table() + -- It's fine to only sample the middle + local area = {left_top = {-400, -400}, right_bottom = {400, 400}} - local biters = surface.find_entities_filtered({type = 'unit', force = 'enemy', area = area}) - if not biters[1] then - return - end - local raffle = objective.biter_raffle - local i = 1 - for key, e in pairs(biters) do - if key % 5 == 0 then - raffle[i] = e.name - i = i + 1 - end - end + local biters = surface.find_entities_filtered({type = "unit", force = "enemy", area = area}) + if not biters[1] then return end + local raffle = objective.biter_raffle + local i = 1 + for key, e in pairs(biters) do + if key % 5 == 0 then + raffle[i] = e.name + i = i + 1 + end + end end local function is_biter_inactive(biter) - if not biter.entity then - --print("AI: active unit " .. unit_number .. " removed, possibly died.") - return true - end - if not biter.entity.valid then - --print("AI: active unit " .. unit_number .. " removed, biter invalid.") - return true - end - if not biter.entity.unit_group then - --print("AI: active unit " .. unit_number .. " at x" .. biter.entity.position.x .. " y" .. biter.entity.position.y .. " removed, had no unit group.") - return true - end - if not biter.entity.unit_group.valid then - --print("AI: active unit " .. unit_number .. " removed, unit group invalid.") - return true - end - if game.tick - biter.active_since > 162000 then - --print("AI: " .. "enemy" .. " unit " .. unit_number .. " timed out at tick age " .. game.tick - biter.active_since .. ".") - biter.entity.destroy() - return true - end + if not biter.entity then + --print("AI: active unit " .. unit_number .. " removed, possibly died.") + return true + end + if not biter.entity.valid then + --print("AI: active unit " .. unit_number .. " removed, biter invalid.") + return true + end + if not biter.entity.unit_group then + --print("AI: active unit " .. unit_number .. " at x" .. biter.entity.position.x .. " y" .. biter.entity.position.y .. " removed, had no unit group.") + return true + end + if not biter.entity.unit_group.valid then + --print("AI: active unit " .. unit_number .. " removed, unit group invalid.") + return true + end + if game.tick - biter.active_since > 162000 then + --print("AI: " .. "enemy" .. " unit " .. unit_number .. " timed out at tick age " .. game.tick - biter.active_since .. ".") + biter.entity.destroy() + return true + end end local function set_active_biters(group) - local objective = Chrono_table.get_table() - if not group.valid then - return - end - local active_biters = objective.active_biters + local objective = Chrono_table.get_table() + if not group.valid then + return + end + local active_biters = objective.active_biters - for _, unit in pairs(group.members) do - if not active_biters[unit.unit_number] then - active_biters[unit.unit_number] = {entity = unit, active_since = game.tick} - end - end + for _, unit in pairs(group.members) do + if not active_biters[unit.unit_number] then + active_biters[unit.unit_number] = {entity = unit, active_since = game.tick} + end + end end Public.destroy_inactive_biters = function() - local objective = Chrono_table.get_table() - if objective.chronotimer < 100 then - return - end - for _, group in pairs(objective.unit_groups) do - set_active_biters(group) - end + local objective = Chrono_table.get_table() + if objective.passivetimer < 60 then + return + end + for _, group in pairs(objective.unit_groups) do + set_active_biters(group) + end - for unit_number, biter in pairs(objective.active_biters) do - if is_biter_inactive(biter, unit_number) then - objective.active_biters[unit_number] = nil - end - end + for unit_number, biter in pairs(objective.active_biters) do + if is_biter_inactive(biter, unit_number) then + objective.active_biters[unit_number] = nil + end + end end local function colonize(unit_group) - local surface = unit_group.surface - local evo = math_floor(game.forces['enemy'].evolution_factor * 20) - local nests = math_random(1 + evo, 2 + evo * 2) - local commands = {} - local biters = - surface.find_entities_filtered { - position = unit_group.position, - radius = 30, - name = biter_raffle, - force = 'enemy' - } - local goodbiters = {} - if #biters > 1 then - for i = 1, #biters, 1 do - if biters[i].unit_group == unit_group then - goodbiters[#goodbiters + 1] = biters[i] - end - end - end - local eligible_spawns - if #goodbiters < 10 then - --game.print("no biters to colonize") - if #unit_group.members < 10 then - unit_group.destroy() - end - return - else - eligible_spawns = 1 + math_floor(#goodbiters / 10) - end - local success = false + local surface = unit_group.surface + local evo = math_floor(game.forces['enemy'].evolution_factor * 20) + local nests = math_random(1 + evo, 2 + evo * 2) + local commands = {} + local biters = + surface.find_entities_filtered { + position = unit_group.position, + radius = 30, + name = biter_raffle, + force = 'enemy' + } + local goodbiters = {} + if #biters > 1 then + for i = 1, #biters, 1 do + if biters[i].unit_group == unit_group then + goodbiters[#goodbiters + 1] = biters[i] + end + end + end + local eligible_spawns + if #goodbiters < 10 then + --game.print("no biters to colonize") + if #unit_group.members < 10 then + unit_group.destroy() + end + return + else + eligible_spawns = 1 + math_floor(#goodbiters / 10) + end + local success = false - for i = 1, nests, 1 do - if eligible_spawns < i then - break - end - local pos = surface.find_non_colliding_position('rocket-silo', unit_group.position, 20, 1, true) - if not pos then - local items = - surface.find_entities_filtered { - position = unit_group.position, - radius = 32, - type = 'item-entity', - name = 'item-on-ground' - } - if #items > 0 then - for i = 1, #items, 1 do - if items[i].stack.name == 'stone' then - items[i].destroy() - end - end - pos = surface.find_non_colliding_position('rocket-silo', unit_group.position, 20, 1, true) - end - end - if pos then - --game.print("[gps=" .. e.position.x .. "," .. e.position.y .. "]") - success = true - if math_random(1, 5) == 1 then - surface.create_entity( - { - name = worm_raffle[1 + math_floor((game.forces['enemy'].evolution_factor - 0.000001) * 4)], - position = pos, - force = unit_group.force - } - ) - else - surface.create_entity( - {name = spawner_raffle[math_random(1, #spawner_raffle)], position = pos, force = unit_group.force} - ) - end - else - local obstacles = - surface.find_entities_filtered { - position = unit_group.position, - radius = 10, - type = {'simple-entity', 'tree'}, - limit = 50 - } - if obstacles then - for i = 1, #obstacles, 1 do - if obstacles[i].valid then - commands[#commands + 1] = { - type = defines.command.attack, - target = obstacles[i], - distraction = defines.distraction.by_enemy - } - end - end - end - end - end - if success then - for i = 1, #goodbiters, 1 do - if goodbiters[i].valid then - goodbiters[i].destroy() - end - end - end - if #commands > 0 then - --game.print("Attacking [gps=" .. commands[1].target.position.x .. "," .. commands[1].target.position.y .. "]") - unit_group.set_command( - { - type = defines.command.compound, - structure_type = defines.compound_command.return_last, - commands = commands - } - ) - end + for i = 1, nests, 1 do + if eligible_spawns < i then + break + end + local pos = surface.find_non_colliding_position('rocket-silo', unit_group.position, 20, 1, true) + if not pos then + local items = + surface.find_entities_filtered { + position = unit_group.position, + radius = 32, + type = 'item-entity', + name = 'item-on-ground' + } + if #items > 0 then + for i = 1, #items, 1 do + if items[i].stack.name == 'stone' then + items[i].destroy() + end + end + pos = surface.find_non_colliding_position('rocket-silo', unit_group.position, 20, 1, true) + end + end + if pos then + --game.print("[gps=" .. e.position.x .. "," .. e.position.y .. "]") + success = true + if math_random(1, 5) == 1 then + surface.create_entity( + { + name = worm_raffle[1 + math_floor((game.forces['enemy'].evolution_factor - 0.000001) * 4)], + position = pos, + force = unit_group.force + } + ) + else + surface.create_entity( + {name = spawner_raffle[math_random(1, #spawner_raffle)], position = pos, force = unit_group.force} + ) + end + else + local obstacles = + surface.find_entities_filtered { + position = unit_group.position, + radius = 10, + type = {'simple-entity', 'tree'}, + limit = 50 + } + if obstacles then + for i = 1, #obstacles, 1 do + if obstacles[i].valid then + commands[#commands + 1] = { + type = defines.command.attack, + target = obstacles[i], + distraction = defines.distraction.by_enemy + } + end + end + end + end + end + if success then + for i = 1, #goodbiters, 1 do + if goodbiters[i].valid then + goodbiters[i].destroy() + end + end + end + if #commands > 0 then + --game.print("Attacking [gps=" .. commands[1].target.position.x .. "," .. commands[1].target.position.y .. "]") + unit_group.set_command( + { + type = defines.command.compound, + structure_type = defines.compound_command.return_last, + commands = commands + } + ) + end - --unit_group.destroy() + --unit_group.destroy() end Public.send_near_biters_to_objective = function() - local Diff = Difficulty.get() + local objective = Chrono_table.get_table() + if objective.chronojumps == 0 then return end + if not objective.locomotive then return end + if not objective.locomotive_cargo[1] then return end + if not objective.locomotive_cargo[2] then return end + if not objective.locomotive_cargo[3] then return end + local targets = {objective.locomotive, objective.locomotive, objective.locomotive_cargo[1], objective.locomotive_cargo[2], objective.locomotive_cargo[3]} + local random_target = targets[math_random(1, #targets)] + if objective.game_lost then return end + local surface = random_target.surface + local pollution = surface.get_pollution(random_target.position) + local success = false - local objective = Chrono_table.get_table() - if game.tick < 36000 then - return - end - if not objective.locomotive then - return - end - if not objective.locomotive_cargo[1] then - return - end - if not objective.locomotive_cargo[2] then - return - end - if not objective.locomotive_cargo[3] then - return - end - local targets = { - objective.locomotive, - objective.locomotive, - objective.locomotive_cargo[1], - objective.locomotive_cargo[2], - objective.locomotive_cargo[3] - } - local random_target = targets[math_random(1, #targets)] - if objective.game_lost then - return - end - local surface = random_target.surface - local pollution = surface.get_pollution(random_target.position) - local success = false - if pollution > 200 * (1 / Diff.difficulty_vote_value) or objective.planet[1].name.id == 17 then - surface.pollute(random_target.position, -50 * (1 / Diff.difficulty_vote_value)) - --game.print("sending objective wave") - success = true + local difficulty = Difficulty.get().difficulty_vote_value + if pollution > 4 * Balance.pollution_spent_per_attack(difficulty) or objective.planet[1].type.id == 17 then + local pollution_to_eat = Balance.pollution_spent_per_attack(difficulty) + surface.pollute(random_target.position, -pollution_to_eat) + game.pollution_statistics.on_flow("biter-spawner", -pollution_to_eat) + success = true + else + if objective.chronojumps < 50 then + if math_random(1, 50 - objective.chronojumps) == 1 then success = true end + -- game.print("not enough pollution for objective attack") else - if objective.chronojumps < 50 then - --game.print("not enough pollution for objective attack") - if math_random(1, 50 - objective.chronojumps) == 1 then - success = true - end - else - success = true - end - end - if success then - game.surfaces[objective.active_surface_index].set_multi_command( - { - command = { - type = defines.command.attack, - target = random_target, - distraction = defines.distraction.none - }, - unit_count = 16 + - math_random(1, math_floor(1 + game.forces['enemy'].evolution_factor * 100)) * - Diff.difficulty_vote_value, - force = 'enemy', - unit_search_distance = 128 - } - ) + success = true end + end + if success then + -- game.print("sending objective wave") + game.surfaces[objective.active_surface_index].set_multi_command({ + command={ + type=defines.command.attack, + target=random_target, + distraction=defines.distraction.none + }, + unit_count = 16 + math_random(1, math_floor(1 + game.forces["enemy"].evolution_factor * 100)) * Difficulty.get().difficulty_vote_value, + force = "enemy", + unit_search_distance=128 + }) + end end + local function get_random_close_spawner(surface) - local area = {left_top = {-1100, -500}, right_bottom = {1100, 500}} + local area = {left_top = {-1100, -500}, right_bottom = {1100, 500}} - local spawners = surface.find_entities_filtered({type = 'unit-spawner', force = 'enemy', area = area}) - if not spawners[1] then - return false - end + local spawners = surface.find_entities_filtered({type = "unit-spawner", force = "enemy", area = area}) + if not spawners[1] then return false end - local spawner = spawners[math_random(1, #spawners)] - for i = 1, 5, 1 do - local spawner_2 = spawners[math_random(1, #spawners)] - if spawner_2.position.x ^ 2 + spawner_2.position.y ^ 2 < spawner.position.x ^ 2 + spawner.position.y ^ 2 then - spawner = spawner_2 - end - end + local spawner = spawners[math_random(1,#spawners)] + for i = 1, 5, 1 do + local spawner_2 = spawners[math_random(1,#spawners)] + if spawner_2.position.x ^ 2 + spawner_2.position.y ^ 2 < spawner.position.x ^ 2 + spawner.position.y ^ 2 then spawner = spawner_2 end + end - return spawner + return spawner end + local function select_units_around_spawner(spawner) - local Diff = Difficulty.get() + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value - local biters = spawner.surface.find_enemy_units(spawner.position, 160, 'player') - if not biters[1] then - return false - end - local valid_biters = {} - local objective = Chrono_table.get_table() + local biters = spawner.surface.find_enemy_units(spawner.position, 160, "player") + if not biters[1] then return false end + local valid_biters = {} - local unit_count = 0 - local max_unit_count = 128 * Diff.difficulty_vote_value + local unit_count = 0 - for _, biter in pairs(biters) do - if unit_count >= max_unit_count then - break - end - if biter.force.name == 'enemy' and objective.active_biters[biter.unit_number] == nil then - valid_biters[#valid_biters + 1] = biter - objective.active_biters[biter.unit_number] = {entity = biter, active_since = game.tick} - unit_count = unit_count + 1 - end - end + for _, biter in pairs(biters) do + if unit_count >= Balance.max_new_attack_group_size(difficulty) then break end + if biter.force.name == "enemy" and objective.active_biters[biter.unit_number] == nil then + valid_biters[#valid_biters + 1] = biter + objective.active_biters[biter.unit_number] = {entity = biter, active_since = game.tick} + unit_count = unit_count + 1 + end + end - --Manual spawning of additional units - local size_of_biter_raffle = #objective.biter_raffle - if size_of_biter_raffle > 0 then - for _ = 1, max_unit_count - unit_count, 1 do - local biter_name = objective.biter_raffle[math_random(1, size_of_biter_raffle)] - local position = spawner.surface.find_non_colliding_position(biter_name, spawner.position, 128, 2) - if not position then - break - end + --Manual spawning of additional units + local size_of_biter_raffle = #objective.biter_raffle + if size_of_biter_raffle > 0 then + for _ = 1, Balance.max_new_attack_group_size(difficulty) - unit_count, 1 do + local biter_name = objective.biter_raffle[math_random(1, size_of_biter_raffle)] + local position = spawner.surface.find_non_colliding_position(biter_name, spawner.position, 128, 2) + if not position then break end - local biter = spawner.surface.create_entity({name = biter_name, force = 'enemy', position = position}) + local biter = spawner.surface.create_entity({name = biter_name, force = "enemy", position = position}) - valid_biters[#valid_biters + 1] = biter - objective.active_biters[biter.unit_number] = {entity = biter, active_since = game.tick} - end - end - return valid_biters + valid_biters[#valid_biters + 1] = biter + objective.active_biters[biter.unit_number] = {entity = biter, active_since = game.tick} + end + end + return valid_biters end -local function send_group(unit_group, nearest_player_unit) - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - local targets = { - objective.locomotive, - objective.locomotive, - nearest_player_unit, - nearest_player_unit, - nearest_player_unit, - objective.locomotive_cargo[1], - objective.locomotive_cargo[2], - objective.locomotive_cargo[3] - } - local target = targets[math_random(1, #targets)] - if not target.valid then - colonize(unit_group) - return +local function generate_attack_target(nearest_player_unit) + local objective = Chrono_table.get_table() + + local target = Rand.raffle( + { + nearest_player_unit, + objective.locomotive, + objective.locomotive_cargo[1], + objective.locomotive_cargo[2], + objective.locomotive_cargo[3], + "pumpjack", + "radar" + }, + {3, 2, 1, 1, 1, 2, 1} + ) + + if target == "pumpjack" or target == "radar" then + local entities = game.surfaces[objective.active_surface_index].find_entities_filtered({ + name = target + }) + entities=Rand.shuffle(entities) + local entity = false + for _, e in pairs(entities) do + if e.is_connected_to_electric_network() + then + entity = e + end end - local surface = target.surface - local pollution = surface.get_pollution(target.position) - if pollution > 200 * (1 / Diff.difficulty_vote_value) or objective.planet[1].name.id == 17 then - surface.pollute(target.position, -50 * (1 / Diff.difficulty_vote_value)) - --game.print("sending unit group attack") - local commands = {} - - local vector = attack_vectors[math_random(1, size_of_vectors)] - local position = {target.position.x + vector[1], target.position.y + vector[2]} - position = unit_group.surface.find_non_colliding_position('stone-furnace', position, 96, 1) - if position then - commands[#commands + 1] = { - type = defines.command.attack_area, - destination = position, - radius = 24, - distraction = defines.distraction.by_enemy - } - end - - commands[#commands + 1] = { - type = defines.command.attack_area, - destination = target.position, - radius = 32, - distraction = defines.distraction.by_enemy - } - - commands[#commands + 1] = { - type = defines.command.attack, - target = target, - distraction = defines.distraction.by_enemy - } - - unit_group.set_command( - { - type = defines.command.compound, - structure_type = defines.compound_command.return_last, - commands = commands - } - ) + if entity and entity.valid then + target = entity else - --game.print("not enough pollution for unit attack") - colonize(unit_group) + target = objective.locomotive end - return true + end + + return target +end + + +local function send_group(unit_group, nearest_player_unit) + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + local target = generate_attack_target(nearest_player_unit) + + if not target.valid then colonize(unit_group) return end + local surface = target.surface + local pollution = surface.get_pollution(target.position) + + if pollution > 4 * Balance.pollution_spent_per_attack(difficulty) or objective.planet[1].type.id == 17 then + + local pollution_to_eat = Balance.pollution_spent_per_attack(difficulty) + surface.pollute(target.position, -pollution_to_eat) + game.pollution_statistics.on_flow("biter-spawner", -pollution_to_eat) + + + if #unit_group.members > 0 then game.pollution_statistics.on_flow(unit_group.members[1].name or "small-biter", - pollution_to_eat) end + + local commands = {} + + local vector = attack_vectors[math_random(1, size_of_vectors)] + local position = {target.position.x + vector[1], target.position.y + vector[2]} + position = unit_group.surface.find_non_colliding_position("stone-furnace", position, 96, 1) + if position then + + -- game.print("group of " .. #unit_group.members .. " to " .. position.x .. ", " .. position.y) + + commands[#commands + 1] = { + type = defines.command.attack_area, + destination = position, + radius = 24, + distraction = defines.distraction.by_enemy + } + end + + -- game.print("group of " .. #unit_group.members .. " to " .. target.position.x .. ", " .. target.position.y) + + commands[#commands + 1] = { + type = defines.command.attack_area, + destination = target.position, + radius = 32, + distraction = defines.distraction.by_enemy + } + + commands[#commands + 1] = { + type = defines.command.attack, + target = target, + distraction = defines.distraction.by_enemy + } + + unit_group.set_command({ + type = defines.command.compound, + structure_type = defines.compound_command.return_last, + commands = commands + }) + else + --game.print("not enough pollution for unit attack") + colonize(unit_group) + end + return true end local function is_chunk_empty(surface, area) - if surface.count_entities_filtered({type = {'unit-spawner', 'unit'}, area = area}) ~= 0 then - return false - end - if surface.count_entities_filtered({force = 'player', area = area}) ~= 0 then - return false - end - if surface.count_tiles_filtered({name = {'water', 'deepwater'}, area = area}) ~= 0 then - return false - end - return true + if surface.count_entities_filtered({type = {"unit-spawner", "unit"}, area = area}) ~= 0 then return false end + if surface.count_entities_filtered({force = "player", area = area}) ~= 0 then return false end + if surface.count_tiles_filtered({name = {"water", "deepwater"}, area = area}) ~= 0 then return false end + return true end local function get_unit_group_position(surface, nearest_player_unit, spawner) - if math_random(1, 3) ~= 1 then - local spawner_chunk_position = { - x = math.floor(spawner.position.x / 32), - y = math.floor(spawner.position.y / 32) - } - local valid_chunks = {} - for x = -2, 2, 1 do - for y = -2, 2, 1 do - local chunk = {x = spawner_chunk_position.x + x, y = spawner_chunk_position.y + y} - local area = {{chunk.x * 32, chunk.y * 32}, {chunk.x * 32 + 32, chunk.y * 32 + 32}} - if is_chunk_empty(surface, area) then - valid_chunks[#valid_chunks + 1] = chunk - end - end - end + if math_random(1,3) ~= 1 then + local spawner_chunk_position = {x = math.floor(spawner.position.x / 32), y = math.floor(spawner.position.y / 32)} + local valid_chunks = {} + for x = -2, 2, 1 do + for y = -2, 2, 1 do + local chunk = {x = spawner_chunk_position.x + x, y = spawner_chunk_position.y + y} + local area = {{chunk.x * 32, chunk.y * 32},{chunk.x * 32 + 32, chunk.y * 32 + 32}} + if is_chunk_empty(surface, area) then + valid_chunks[#valid_chunks + 1] = chunk + end + end + end - if #valid_chunks > 0 then - local chunk = valid_chunks[math_random(1, #valid_chunks)] - return {x = chunk.x * 32 + 16, y = chunk.y * 32 + 16} - end - end + if #valid_chunks > 0 then + local chunk = valid_chunks[math_random(1, #valid_chunks)] + return {x = chunk.x * 32 + 16, y = chunk.y * 32 + 16} + end + end - local unit_group_position = { - x = (spawner.position.x + nearest_player_unit.position.x * 0.2), - y = (spawner.position.y + nearest_player_unit.position.y * 0.2) - } - local pos = surface.find_non_colliding_position('rocket-silo', unit_group_position, 256, 1) - if pos then - unit_group_position = pos - end + local unit_group_position = {x = (spawner.position.x + nearest_player_unit.position.x * 0.2) , y = (spawner.position.y + nearest_player_unit.position.y * 0.2)} + local pos = surface.find_non_colliding_position("rocket-silo", unit_group_position, 256, 1) + if pos then unit_group_position = pos end - if not unit_group_position then - return false - end - return unit_group_position + if not unit_group_position then + return false + end + return unit_group_position end local function create_attack_group(surface) - local objective = Chrono_table.get_table() - if 256 - get_active_biter_count() < 256 then - return false - end - local spawner = get_random_close_spawner(surface) - if not spawner then - return false - end - local nearest_player_unit = - surface.find_nearest_enemy({position = spawner.position, max_distance = 1024, force = 'enemy'}) - if not nearest_player_unit then - nearest_player_unit = objective.locomotive - end - local unit_group_position = get_unit_group_position(surface, nearest_player_unit, spawner) - local units = select_units_around_spawner(spawner) - if not units then - return false - end - local unit_group = surface.create_unit_group({position = unit_group_position, force = 'enemy'}) - for _, unit in pairs(units) do - unit_group.add_member(unit) - end - send_group(unit_group, nearest_player_unit) - objective.unit_groups[unit_group.group_number] = unit_group + local objective = Chrono_table.get_table() + if 256 - get_active_biter_count() < 256 then + return false + end + local spawner = get_random_close_spawner(surface) + if not spawner then + return false + end + local nearest_player_unit = surface.find_nearest_enemy({position = spawner.position, max_distance = 1024, force = "enemy"}) + if not nearest_player_unit then nearest_player_unit = objective.locomotive end + local unit_group_position = get_unit_group_position(surface, nearest_player_unit, spawner) + local units = select_units_around_spawner(spawner) + if not units then return false end + local unit_group = surface.create_unit_group({position = unit_group_position, force = "enemy"}) + for _, unit in pairs(units) do unit_group.add_member(unit) end + send_group(unit_group, nearest_player_unit) + objective.unit_groups[unit_group.group_number] = unit_group + end -- Public.rogue_group = function() -- local objective = Chrono_table.get_table() --- if objective.chronotimer < 100 then return end +-- if objective.passivetimer < 60 then return end -- if not objective.locomotive then return end -- local surface = game.surfaces[objective.active_surface_index] -- local spawner = get_random_close_spawner(surface) @@ -521,106 +508,61 @@ end -- end Public.pre_main_attack = function() - local objective = Chrono_table.get_table() - if objective.chronotimer < 100 then - return - end - local surface = game.surfaces[objective.active_surface_index] - set_biter_raffle_table(surface) + local objective = Chrono_table.get_table() + if objective.chronojumps == 0 then return end + local surface = game.surfaces[objective.active_surface_index] + set_biter_raffle_table(surface) end Public.perform_main_attack = function() - local objective = Chrono_table.get_table() - if objective.chronotimer < 100 then - return - end - local surface = game.surfaces[objective.active_surface_index] - create_attack_group(surface) + local objective = Chrono_table.get_table() + if objective.chronojumps == 0 then return end + local surface = game.surfaces[objective.active_surface_index] + create_attack_group(surface) end Public.wake_up_sleepy_groups = function() - local objective = Chrono_table.get_table() - if objective.chronotimer < 100 then - return - end - local entity - local unit_group - for _, biter in pairs(objective.active_biters) do - entity = biter.entity - if entity then - if entity.valid then - unit_group = entity.unit_group - if unit_group then - if unit_group.valid then - if unit_group.state == defines.group_state.finished then - local nearest_player_unit = - entity.surface.find_nearest_enemy( - {position = entity.position, max_distance = 2048, force = 'enemy'} - ) - if not nearest_player_unit then - nearest_player_unit = objective.locomotive - end - local destination = - unit_group.surface.find_non_colliding_position( - 'rocket-silo', - unit_group.position, - 32, - 1 - ) - if not destination then - destination = { - x = unit_group.position.x + math_random(-10, 10), - y = unit_group.position.y + math_random(-10, 10) - } - end - unit_group.set_command( - { - type = defines.command.go_to_location, - destination = destination, - distraction = defines.distraction.by_enemy - } - ) - send_group(unit_group, nearest_player_unit) - return - elseif - unit_group.state == defines.group_state.gathering and - not unit_group.surface.find_non_colliding_position( - 'rocket-silo', - unit_group.position, - 3, - 1 - ) - then - local destination = - unit_group.surface.find_non_colliding_position( - 'rocket-silo', - unit_group.position, - 32, - 1 - ) - if not destination then - destination = { - x = unit_group.position.x + math_random(-10, 10), - y = unit_group.position.y + math_random(-10, 10) - } - end - unit_group.set_command( - { - type = defines.command.go_to_location, - destination = destination, - distraction = defines.distraction.by_enemy - } - ) - -- local nearest_player_unit = entity.surface.find_nearest_enemy({position = entity.position, max_distance = 2048, force = "enemy"}) - -- if not nearest_player_unit then nearest_player_unit = objective.locomotive end - -- send_group(unit_group, nearest_player_unit) - return - end - end - end + local objective = Chrono_table.get_table() + if objective.chronojumps == 0 then return end + local entity + local unit_group + for _, biter in pairs(objective.active_biters) do + entity = biter.entity + if entity then + if entity.valid then + unit_group = entity.unit_group + if unit_group then + if unit_group.valid then + if unit_group.state == defines.group_state.finished then + local nearest_player_unit = entity.surface.find_nearest_enemy({position = entity.position, max_distance = 2048, force = "enemy"}) + if not nearest_player_unit then nearest_player_unit = objective.locomotive end + local destination = unit_group.surface.find_non_colliding_position("rocket-silo", unit_group.position, 32, 1) + if not destination then destination = {x = unit_group.position.x + math_random(-10,10), y = unit_group.position.y + math_random(-10,10)} end + unit_group.set_command({ + type = defines.command.go_to_location, + destination = destination, + distraction = defines.distraction.by_enemy + }) + send_group(unit_group, nearest_player_unit) + return + elseif unit_group.state == defines.group_state.gathering and not unit_group.surface.find_non_colliding_position("rocket-silo", unit_group.position, 3, 1) then + local destination = unit_group.surface.find_non_colliding_position("rocket-silo", unit_group.position, 32, 1) + if not destination then destination = {x = unit_group.position.x + math_random(-10,10), y = unit_group.position.y + math_random(-10,10)} end + unit_group.set_command({ + type = defines.command.go_to_location, + destination = destination, + distraction = defines.distraction.by_enemy + }) + -- local nearest_player_unit = entity.surface.find_nearest_enemy({position = entity.position, max_distance = 2048, force = "enemy"}) + -- if not nearest_player_unit then nearest_player_unit = objective.locomotive end + -- send_group(unit_group, nearest_player_unit) + return end - end - end + end + end + end + end + end end return Public diff --git a/maps/chronosphere/balance.lua b/maps/chronosphere/balance.lua new file mode 100644 index 00000000..67496184 --- /dev/null +++ b/maps/chronosphere/balance.lua @@ -0,0 +1,334 @@ +local Public = {} +local Rand = require 'maps.chronosphere.random' + +local math_floor = math.floor +local math_min = math.min +local math_max = math.max +local math_abs = math.abs +local math_ceil = math.ceil +local math_pow = math.pow +local math_random = math.random +local math_log = math.log + + + +--- DIFFICULTY SCALING CURVES --- + +local function difficulty_sloped(difficulty,slope) + + return 1 + ((difficulty - 1) * slope) +end +-- SLOPE GUIDE +-- slope 1 -> {0.25, 0.50, 0.75, 1.00, 1.50, 3.00, 5.00} +-- slope 4/5 -> {0.20, 0.40, 0.60, 0.80, 1.20, 2.40, 4.00} +-- slope 3/5 -> {0.15, 0.30, 0.45, 0.60, 0.90, 1.80, 3.00} +-- slope 2/5 -> {0.10, 0.20, 0.30, 0.40, 0.60, 1.20, 2.00} + +local function difficulty_exp(difficulty,exponent) + + return math_floor(math_pow(difficulty,exponent)) +end +-- EXPONENT GUIDE +-- exponent 1 -> {0.25, 0.50, 0.75, 1.00, 1.50, 3.00, 5.00} +-- exponent 1.5 -> {0.13, 0.35, 0.65, 1.00, 1.84, 5.20, 11.18} +-- exponent 2 -> {0.06, 0.25, 0.56, 1.00, 2.25, 9.00, 25.00} +-- exponent -1.2 -> {5.28, 2.30, 1.41, 1.00, 0.61, 0.27, 0.14} + + + +---- CHRONO/POLLUTION BALANCE ---- + +function Public.pollution_filter_upgrade_factor(upgrades2) + return 1 / (1 + upgrades2 / 4) +end + +function Public.machine_pollution_transfer_from_inside_factor(difficulty, filter_upgrades) return 3 * Public.pollution_filter_upgrade_factor(filter_upgrades) * difficulty_sloped(difficulty, 3/5) end + + +function Public.passive_planet_jumptime(jumps) + local mins + + if jumps < 20 then + mins = 30 + 3 * jumps + else + mins = 90 + end + + return mins * 60 +end + +function Public.generate_jump_countdown_length(difficulty) + if difficulty <= 1 then + return Rand.raffle({90,120,150,180,210,240,270},{1,2,14,98,14,2,1}) + else + return 180 -- thesixthroc: suppress rng for speedrunners + end +-- return 180 +end + +function Public.misfire_percentage_chance(difficulty) + if difficulty <= 1 and difficulty > 0.25 then + return 4 + else + return 0 -- thesixthroc: suppress rng for speedrunners + end +-- return 0 +end + +function Public.passive_pollution_rate(jumps, difficulty, filter_upgrades) + local baserate = 5 * jumps + + local modifiedrate = baserate * Public.pollution_filter_upgrade_factor(filter_upgrades) * math_max(0, difficulty_sloped(difficulty, 5/4)) + + return modifiedrate +end + +function Public.pollution_per_MJ_actively_charged(jumps, difficulty, filter_upgrades) + + local baserate = 2 * (10 + jumps) + + local modifiedrate = baserate * Public.pollution_filter_upgrade_factor(filter_upgrades) + + if difficulty < 1 then + modifiedrate = modifiedrate * difficulty_sloped(difficulty, 1) + else + modifiedrate = modifiedrate + end + + return modifiedrate +end + +function Public.countdown_pollution_rate(jumps, difficulty) + local baserate = 40 * (10 + jumps) * math_max(0, difficulty_sloped(difficulty, 5/4)) + + local modifiedrate = baserate -- thesixthroc: Constant, because part of drama of planet progression. Interpret this as hyperwarp portal pollution + + return modifiedrate +end + +function Public.post_jump_initial_pollution(jumps, difficulty) + local baserate = 200 * (1 + jumps) * math_max(0, difficulty_sloped(difficulty, 5/4)) + + local modifiedrate = baserate -- thesixthroc: Constant, because part of drama of planet progression. Interpret this as hyperwarp portal pollution + + return modifiedrate +end + + +function Public.pollution_spent_per_attack(difficulty) return 60 * difficulty_exp(difficulty, -1.4) end + +function Public.defaultai_attack_pollution_consumption_modifier(difficulty) return 0.8 * difficulty_exp(difficulty, -1.4) end + +function Public.MJ_needed_for_full_charge(difficulty, jumps) + local baserate = 2000 + 500 * jumps + + local modifiedrate + if difficulty <= 1 then modifiedrate = baserate end + if difficulty > 1 and jumps>0 then modifiedrate = baserate + 1000 end + return modifiedrate +end + + + +----- GENERAL BALANCE ---- + +Public.Chronotrain_max_HP = 10000 +Public.Chronotrain_HP_repaired_per_pack = 150 +Public.Tech_price_multiplier = 0.7 + +Public.starting_items = {['pistol'] = 1, ['firearm-magazine'] = 32, ['grenade'] = 2, ['raw-fish'] = 4, ['wood'] = 16} +Public.wagon_starting_items = {{name = 'firearm-magazine', count = 16},{name = 'iron-plate', count = 16},{name = 'wood', count = 16},{name = 'burner-mining-drill', count = 8}} + +function Public.jumps_until_overstay_is_on(difficulty) --both overstay penalties, and evoramp + if difficulty > 1 then return 2 + elseif difficulty == 1 then return 3 + else return 5 + end +end + +function Public.player_gun_speed_modifiers() -- modifiers are fractional + local data = { + ['artillery-shell'] = 0, + ['biological'] = 0, + ['bullet'] = 0, + ['cannon-shell'] = 0, + ['capsule'] = 0, + ['combat-robot-beam'] = 0, + ['combat-robot-laser'] = 0, + ['electric'] = 0, + ['flamethrower'] = 0, --these nerfs are elsewhere for finer control + ['grenade'] = -0.2, + ['landmine'] = 0, + ['laser-turret'] = 0, + ['melee'] = 0, -- doesn't do anything + ['railgun'] = 0, + ['rocket'] = 0, + ['shotgun-shell'] = 0 + } + return data +end +function Public.player_ammo_damage_modifiers() -- bullet affects gun turrets, but flamethrower does not affect flamer turrets + local data = { + ['artillery-shell'] = 0, + ['biological'] = 0, + ['bullet'] = 0, + ['cannon-shell'] = 0, + ['capsule'] = 0, + ['combat-robot-beam'] = 0, + ['combat-robot-laser'] = 0, + ['electric'] = 0, + ['flamethrower'] = 0, --these nerfs are elsewhere for finer control + ['grenade'] = 0, + ['landmine'] = 0, + ['laser-turret'] = 0, + ['melee'] = 0, -- doesn't do anything + ['railgun'] = 0, + ['rocket'] = 0, + ['shotgun-shell'] = 0.1 + } + return data +end +function Public.pistol_damage_multiplier(difficulty) return 2.5 end --3 will one-shot biters + + + +function Public.coin_reward_per_second_jumped_early(seconds, difficulty) + local minutes = seconds / 60 + local amount = minutes * 25 * difficulty_sloped(difficulty, 0) -- No difficulty scaling seems best. (if this is changed, change the code so that coins are not awarded on the first jump) + return math_max(0,math_floor(amount)) +end + +function Public.upgrades_coin_cost_difficulty_scaling(difficulty) return difficulty_sloped(difficulty, 3/5) end + +function Public.flamers_nerfs_size(jumps, difficulty) return 0.02 * jumps * difficulty_sloped(difficulty, 1/2) end + +function Public.max_new_attack_group_size(difficulty) return math_max(200,math_floor(120 * difficulty_sloped(difficulty, 1))) end + +function Public.evoramp50_multiplier_per_10s(difficulty) return (1 + 1/200 * difficulty_sloped(difficulty, 3/5)) end + +function Public.nukes_looted_per_silo(difficulty) return math_max(10, 10 * math_ceil(difficulty_sloped(difficulty, 1))) end + +Public.biome_weights = { + ironwrld = 1, + copperwrld = 1, + stonewrld = 1, + oilwrld = 1, + uraniumwrld = 1, + mixedwrld = 3, + biterwrld = 4, + dumpwrld = 1, + coalwrld = 1, + scrapwrld = 3, + cavewrld = 1, + forestwrld = 2, + riverwrld = 2, + hellwrld = 1, + startwrld = 0, + mazewrld = 2, + endwrld = 0, + swampwrld = 2, + nukewrld = 0 +} + +function Public.ore_richness_weights(difficulty) + local ores_weights + if difficulty <= 0.25 + then ores_weights = {9,10,9,4,2,0} + elseif difficulty <= 0.5 + then ores_weights = {5,11,12,6,2,0} + elseif difficulty <= 0.75 + then ores_weights = {5,9,12,7,3,0} + elseif difficulty <= 1 + then ores_weights = {4,8,12,8,4,0} + elseif difficulty <= 1.5 + then ores_weights = {2,5,15,9,5,0} + elseif difficulty <= 3 + then ores_weights = {1,4,12,13,6,0} + elseif difficulty >= 5 + then ores_weights = {1,2,10,17,6,0} + end + return { + vrich = ores_weights[1], + rich = ores_weights[2], + normal = ores_weights[3], + poor = ores_weights[4], + vpoor = ores_weights[5], + none = ores_weights[6] + } +end +Public.dayspeed_weights = { + static = 2, + normal = 4, + slow = 3, + superslow = 1, + fast = 3, + superfast = 1 +} +function Public.market_offers() + return { + {price = {{'coin', 40}}, offer = {type = 'give-item', item = "raw-fish"}}, + {price = {{"coin", 40}}, offer = {type = 'give-item', item = 'wood', count = 50}}, + {price = {{"coin", 100}}, offer = {type = 'give-item', item = 'iron-ore', count = 50}}, + {price = {{"coin", 100}}, offer = {type = 'give-item', item = 'copper-ore', count = 50}}, + {price = {{"coin", 100}}, offer = {type = 'give-item', item = 'stone', count = 50}}, -- needed? + {price = {{"coin", 100}}, offer = {type = 'give-item', item = 'coal', count = 50}}, + {price = {{"coin", 400}}, offer = {type = 'give-item', item = 'uranium-ore', count = 50}}, + {price = {{"coin", 50}, {"empty-barrel", 1}}, offer = {type = 'give-item', item = 'crude-oil-barrel', count = 1}}, + {price = {{"coin", 500}, {"steel-plate", 20}, {"electronic-circuit", 20}}, offer = {type = 'give-item', item = 'loader', count = 1}}, + {price = {{"coin", 1000}, {"steel-plate", 40}, {"advanced-circuit", 10}, {"loader", 1}}, offer = {type = 'give-item', item = 'fast-loader', count = 1}}, + {price = {{"coin", 3000}, {"express-transport-belt", 10}, {"fast-loader", 1}}, offer = {type = 'give-item', item = 'express-loader', count = 1}}, + --{price = {{"coin", 5}, {"stone", 100}}, offer = {type = 'give-item', item = 'landfill', count = 1}}, + {price = {{"coin", 2}, {"steel-plate", 1}, {"explosives", 10}}, offer = {type = 'give-item', item = 'land-mine', count = 1}}, + {price = {{"pistol", 1}}, offer = {type = "give-item", item = "iron-plate", count = 100}} + } +end +function Public.initial_cargo_boxes() + return { + {name = "loader", count = 1}, + {name = "coal", count = math_random(32, 64)}, + {name = "coal", count = math_random(32, 64)}, + {name = "iron-ore", count = math_random(32, 128)}, + {name = "copper-ore", count = math_random(32, 128)}, + {name = "empty-barrel", count = math_random(16, 32)}, + {name = "submachine-gun", count = 1}, + {name = "submachine-gun", count = 1}, + {name = "shotgun", count = 1}, + {name = "shotgun", count = 1}, + {name = "shotgun", count = 1}, + {name = "shotgun-shell", count = math_random(4, 5)}, + {name = "shotgun-shell", count = math_random(4, 5)}, + {name = "land-mine", count = math_random(6, 18)}, + -- {name = "grenade", count = math_random(2, 3)}, --make these harder to get + -- {name = "grenade", count = math_random(2, 3)}, + -- {name = "grenade", count = math_random(2, 3)}, + {name = "iron-gear-wheel", count = math_random(7, 15)}, + {name = "iron-gear-wheel", count = math_random(7, 15)}, + {name = "iron-gear-wheel", count = math_random(7, 15)}, + {name = "iron-gear-wheel", count = math_random(7, 15)}, + {name = "iron-plate", count = math_random(15, 23)}, + {name = "iron-plate", count = math_random(15, 23)}, + {name = "iron-plate", count = math_random(15, 23)}, + {name = "iron-plate", count = math_random(15, 23)}, + {name = "copper-plate", count = math_random(15, 23)}, + {name = "copper-plate", count = math_random(15, 23)}, + {name = "copper-plate", count = math_random(15, 23)}, + {name = "copper-plate", count = math_random(15, 23)}, + {name = "firearm-magazine", count = math_random(10, 30)}, + {name = "firearm-magazine", count = math_random(10, 30)}, + {name = "firearm-magazine", count = math_random(10, 30)}, + {name = "rail", count = math_random(16, 24)}, + {name = "rail", count = math_random(16, 24)} + } +end + +function Public.treasure_quantity_difficulty_scaling(difficulty) return difficulty_sloped(difficulty, 1) end + +function Public.Base_ore_loot_yield(jumps) + return 13 + 2 * jumps +end + +function Public.scrap_quantity_multiplier(evolution_factor) + return 1 + 3 * evolution_factor +end + +return Public \ No newline at end of file diff --git a/maps/chronosphere/chrono.lua b/maps/chronosphere/chrono.lua index f9781caf..1aa5a17d 100644 --- a/maps/chronosphere/chrono.lua +++ b/maps/chronosphere/chrono.lua @@ -1,6 +1,7 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' +local Score = require "comfy_panel.score" local Difficulty = require 'modules.difficulty_vote' -local Score = require 'comfy_panel.score' local Public_chrono = {} local Server = require 'utils.server' @@ -8,267 +9,261 @@ local math_random = math.random local math_max = math.max function Public_chrono.get_map_gen_settings() - local seed = math_random(1, 1000000) - local map_gen_settings = { - ['seed'] = seed, - ['width'] = 960, - ['height'] = 960, - ['water'] = 0.1, - ['starting_area'] = 1, - ['cliff_settings'] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0}, - ['default_enable_all_autoplace_controls'] = true, - ['autoplace_settings'] = { - ['entity'] = {treat_missing_as_default = false}, - ['tile'] = {treat_missing_as_default = true}, - ['decorative'] = {treat_missing_as_default = true} - } - } - return map_gen_settings + local seed = math_random(1, 1000000) + local map_gen_settings = { + ["seed"] = seed, + ["width"] = 960, + ["height"] = 960, + ["water"] = 0.1, + ["starting_area"] = 1, + ["cliff_settings"] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0}, + ["default_enable_all_autoplace_controls"] = true, + ["autoplace_settings"] = { + ["entity"] = {treat_missing_as_default = false}, + ["tile"] = {treat_missing_as_default = true}, + ["decorative"] = {treat_missing_as_default = true}, + }, + } + return map_gen_settings end function Public_chrono.restart_settings() - local Diff = Difficulty.get() - local get_score = Score.get_table() - local objective = Chrono_table.get_table() - objective.max_health = 10000 - objective.health = 10000 - objective.poisontimeout = 0 - objective.chronotimer = 0 - objective.passivetimer = 0 - objective.passivejumps = 0 - objective.chrononeeds = 2000 - objective.mainscore = 0 - objective.active_biters = {} - objective.unit_groups = {} - objective.biter_raffle = {} - objective.dangertimer = 1200 - objective.dangers = {} - objective.looted_nukes = 0 - objective.offline_players = {} - objective.nextsurface = nil - for i = 1, 16, 1 do - objective.upgrades[i] = 0 - end - objective.upgrades[10] = 2 --poison - objective.outchests = {} - objective.upgradechest = {} - objective.fishchest = {} - objective.acumulators = {} - objective.comfychests = {} - objective.comfychests2 = {} - objective.locomotive_cargo = {} - for _, player in pairs(game.connected_players) do - objective.flame_boots[player.index] = {fuel = 1, steps = {}} - end - global.bad_fire_history = {} - global.friendly_fire_history = {} - global.landfill_history = {} - global.mining_history = {} - get_score.score_table = {} - Diff.difficulty_poll_closing_timeout = game.tick + 90000 - Diff.difficulty_player_votes = {} + local get_score = Score.get_table() + local objective = Chrono_table.get_table() + objective.max_health = Balance.Chronotrain_max_HP + objective.health = Balance.Chronotrain_max_HP + objective.poisontimeout = 0 + objective.chronocharges = 0 + objective.chronochargesneeded = Balance.MJ_needed_for_full_charge(Difficulty.get().difficulty_vote_value, 0) + objective.passive_chronocharge_rate = Balance.MJ_needed_for_full_charge(Difficulty.get().difficulty_vote_value, 0) / Balance.passive_planet_jumptime(0) --per second rate + objective.accumulator_energy_history = {} + objective.passivetimer = 0 + objective.overstaycount = 0 + objective.jump_countdown_start_time = -1 + objective.jump_countdown_length = -1 + objective.mainscore = 0 + objective.active_biters = {} + objective.unit_groups = {} + objective.biter_raffle = {} + objective.dangertimer = 1200 + objective.dangers = {} + objective.looted_nukes = 0 + objective.offline_players = {} + objective.nextsurface = nil + for i = 1, 16, 1 do + objective.upgrades[i] = 0 + end + objective.upgrades[10] = 2 --poison + objective.outchests = {} + objective.upgradechest = {} + objective.fishchest = {} + objective.accumulators = {} + objective.comfychests = {} + objective.comfychests2 = {} + objective.locomotive_cargo = {} + for _, player in pairs(game.connected_players) do + objective.flame_boots[player.index] = {fuel = 1, steps = {}} + end + global.friendly_fire_history = {} + global.landfill_history = {} + global.mining_history = {} + get_score.score_table = {} + Difficulty.reset_difficulty_poll() + Difficulty.set_poll_closing_timeout(game.tick + 35 * 60 * 60) - game.difficulty_settings.technology_price_multiplier = 0.6 - game.map_settings.enemy_evolution.destroy_factor = 0.005 - game.map_settings.enemy_evolution.pollution_factor = 0 - game.map_settings.enemy_evolution.time_factor = 7e-05 - game.map_settings.enemy_expansion.enabled = true - game.map_settings.enemy_expansion.max_expansion_cooldown = 3600 - game.map_settings.enemy_expansion.min_expansion_cooldown = 3600 - game.map_settings.enemy_expansion.settler_group_max_size = 8 - game.map_settings.enemy_expansion.settler_group_min_size = 16 - game.map_settings.pollution.enabled = true - game.map_settings.pollution.pollution_restored_per_tree_damage = 0.02 - game.map_settings.pollution.min_pollution_to_damage_trees = 1 - game.map_settings.pollution.max_pollution_to_restore_trees = 0 - game.map_settings.pollution.pollution_with_max_forest_damage = 10 - game.map_settings.pollution.pollution_per_tree_damage = 0.1 - game.map_settings.pollution.ageing = 0.1 - game.map_settings.pollution.diffusion_ratio = 0.1 - game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = 5 - game.forces.neutral.character_inventory_slots_bonus = 500 - game.forces.enemy.evolution_factor = 0.0001 - game.forces.scrapyard.set_friend('enemy', true) - game.forces.enemy.set_friend('scrapyard', true) - - game.forces.player.technologies['land-mine'].enabled = false - game.forces.player.technologies['landfill'].enabled = false - game.forces.player.technologies['cliff-explosives'].enabled = false - game.forces.player.technologies['fusion-reactor-equipment'].enabled = false - game.forces.player.technologies['power-armor-mk2'].enabled = false - game.forces.player.technologies['railway'].researched = true - game.forces.player.recipes['pistol'].enabled = false -end - -function Public_chrono.init_setup() - game.forces.player.recipes['pistol'].enabled = false + game.difficulty_settings.technology_price_multiplier = Balance.Tech_price_multiplier + game.map_settings.enemy_evolution.destroy_factor = 0.005 + game.map_settings.enemy_evolution.pollution_factor = 0 + game.map_settings.enemy_evolution.time_factor = 7e-05 + game.map_settings.enemy_expansion.enabled = true + game.map_settings.enemy_expansion.max_expansion_cooldown = 3600 + game.map_settings.enemy_expansion.min_expansion_cooldown = 3600 + game.map_settings.enemy_expansion.settler_group_max_size = 8 + game.map_settings.enemy_expansion.settler_group_min_size = 16 + game.map_settings.enemy_expansion.max_expansion_distance = 9 + game.map_settings.pollution.enabled = true + game.map_settings.pollution.expected_max_per_chunk = 400 + game.map_settings.pollution.min_to_show_per_chunk = 40 + game.map_settings.pollution.pollution_restored_per_tree_damage = 0.02 + game.map_settings.pollution.min_pollution_to_damage_trees = 1 + game.map_settings.pollution.max_pollution_to_restore_trees = 0 + game.map_settings.pollution.pollution_with_max_forest_damage = 10 + game.map_settings.pollution.pollution_per_tree_damage = 0.1 + game.map_settings.pollution.ageing = 0.1 + game.map_settings.pollution.diffusion_ratio = 0.12 + game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = 5 + game.map_settings.unit_group.min_group_gathering_time = 1800 + game.map_settings.unit_group.max_group_gathering_time = 18000 + game.map_settings.unit_group.max_wait_time_for_late_members = 600 + game.forces.neutral.character_inventory_slots_bonus = 500 + game.forces.enemy.evolution_factor = 0.0001 + game.forces.scrapyard.set_friend('enemy', true) + game.forces.enemy.set_friend('scrapyard', true) + game.forces.player.technologies["land-mine"].enabled = false + game.forces.player.technologies["landfill"].enabled = false + game.forces.player.technologies["cliff-explosives"].enabled = false + game.forces.player.technologies["fusion-reactor-equipment"].enabled = false + game.forces.player.technologies["power-armor-mk2"].enabled = false + game.forces.player.technologies["railway"].researched = true + game.forces.player.recipes["pistol"].enabled = false end function Public_chrono.objective_died() - local objective = Chrono_table.get_table() - if objective.game_lost == true then - return - end - objective.health = 0 - local surface = objective.surface - game.print({'chronosphere.message_game_lost1'}) - game.print({'chronosphere.message_game_lost2'}) - for i = 1, 3, 1 do - surface.create_entity({name = 'big-artillery-explosion', position = objective.locomotive_cargo[i].position}) - objective.locomotive_cargo[i].destroy() - end - for i = 1, #objective.comfychests, 1 do - --surface.create_entity({name = "big-artillery-explosion", position = objective.comfychests[i].position}) - objective.comfychests[i].destroy() + local objective = Chrono_table.get_table() + if objective.game_lost == true then return end + objective.health = 0 + local surface = objective.surface + game.print({"chronosphere.message_game_lost1"}) + game.print({"chronosphere.message_game_lost2"}) + for i = 1, 3, 1 do + surface.create_entity({name = "big-artillery-explosion", position = objective.locomotive_cargo[i].position}) + objective.locomotive_cargo[i].destroy() + end + for i = 1, #objective.comfychests,1 do + --surface.create_entity({name = "big-artillery-explosion", position = objective.comfychests[i].position}) + objective.comfychests[i].destroy() - if objective.comfychests2 then - objective.comfychests2[i].destroy() - end + if objective.comfychests2 then objective.comfychests2[i].destroy() end - --objective.comfychests = {} - end - objective.acumulators = {} - objective.game_lost = true - objective.game_reset_tick = game.tick + 1800 - for _, player in pairs(game.connected_players) do - player.play_sound {path = 'utility/game_lost', volume_modifier = 0.75} - end -end - -local function overstayed() - local objective = Chrono_table.get_table() - if objective.passivetimer > objective.chrononeeds * 0.75 and objective.chronojumps > 5 then - objective.passivejumps = objective.passivejumps + 1 - return true - end - return false + --objective.comfychests = {} + end + objective.accumulators = {} + objective.game_lost = true + objective.game_reset_tick = game.tick + 1800 + game.play_sound{path="utility/game_lost", volume_modifier=0.75} end local function check_nuke_silos() - local objective = Chrono_table.get_table() - if objective.dangers and #objective.dangers > 1 then - for i = 1, #objective.dangers, 1 do - if objective.dangers[i].destroyed == true then - objective.looted_nukes = objective.looted_nukes + 5 - end - end - end + local objective = Chrono_table.get_table() + if objective.dangers and #objective.dangers > 1 then + for i = 1, #objective.dangers, 1 do + if objective.dangers[i].destroyed == true then + objective.looted_nukes = objective.looted_nukes + Balance.nukes_looted_per_silo(Difficulty.get().difficulty_vote_value) + end + end + end end function Public_chrono.process_jump() - local objective = Chrono_table.get_table() - local _overstayed = overstayed() - objective.chronojumps = objective.chronojumps + 1 - objective.chrononeeds = 2000 + 300 * objective.chronojumps - objective.active_biters = {} - objective.unit_groups = {} - objective.biter_raffle = {} - objective.passivetimer = 0 - objective.chronotimer = 0 - objective.dangertimer = 1200 - local message = 'Comfylatron: Wheeee! Time Jump Active! This is Jump number ' .. objective.chronojumps - game.print(message, {r = 0.98, g = 0.66, b = 0.22}) - Server.to_discord_embed(message) + local objective = Chrono_table.get_table() - if objective.chronojumps == 6 then - game.print({'chronosphere.message_evolve'}, {r = 0.98, g = 0.36, b = 0.22}) - elseif objective.chronojumps >= 15 and objective.computermessage == 0 then - game.print({'chronosphere.message_quest1'}, {r = 0.98, g = 0.36, b = 0.22}) - objective.computermessage = 1 - elseif objective.chronojumps >= 20 and objective.computermessage == 2 then - game.print({'chronosphere.message_quest3'}, {r = 0.98, g = 0.36, b = 0.22}) - objective.computermessage = 3 - elseif objective.chronojumps >= 25 and objective.computermessage == 4 then - game.print({'chronosphere.message_quest5'}, {r = 0.98, g = 0.36, b = 0.22}) - objective.computermessage = 5 - end - if _overstayed then - game.print({'chronosphere.message_overstay'}, {r = 0.98, g = 0.36, b = 0.22}) - end - if objective.planet[1].name.id == 19 then - check_nuke_silos() - end + objective.chronojumps = objective.chronojumps + 1 + objective.passivetimer = 0 + objective.chronochargesneeded = Balance.MJ_needed_for_full_charge(Difficulty.get().difficulty_vote_value, objective.chronojumps) + objective.passive_chronocharge_rate = Balance.MJ_needed_for_full_charge(Difficulty.get().difficulty_vote_value, objective.chronojumps) / Balance.passive_planet_jumptime(objective.chronojumps) + objective.active_biters = {} + objective.unit_groups = {} + objective.biter_raffle = {} + objective.chronocharges = 0 + objective.jump_countdown_start_time = -1 + objective.jump_countdown_length = -1 + objective.dangertimer = 1200 + local message = "Comfylatron: Wheeee! Time jump underway! This is Jump number " .. objective.chronojumps + game.print(message, {r=0.98, g=0.66, b=0.22}) + Server.to_discord_embed(message) + + if objective.chronojumps == Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) then + game.print({"chronosphere.message_evolve"}, {r=0.98, g=0.36, b=0.22}) + elseif objective.chronojumps >= 15 and objective.computermessage == 0 then + game.print({"chronosphere.message_quest1"}, {r=0.98, g=0.36, b=0.22}) + objective.computermessage = 1 + game.play_sound{path="utility/new_objective", volume_modifier=0.85} + elseif objective.chronojumps >= 20 and objective.computermessage == 2 then + game.print({"chronosphere.message_quest3"}, {r=0.98, g=0.36, b=0.22}) + objective.computermessage = 3 + game.play_sound{path="utility/new_objective", volume_modifier=0.85} + elseif objective.chronojumps >= 25 and objective.computermessage == 4 then + game.print({"chronosphere.message_quest5"}, {r=0.98, g=0.36, b=0.22}) + objective.computermessage = 5 + game.play_sound{path="utility/new_objective", volume_modifier=0.85} + end + if (objective.passivetimer - objective.jump_countdown_length) * objective.passive_chronocharge_rate > objective.chronochargesneeded * 0.75 and objective.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) then + game.print({"chronosphere.message_overstay"}, {r=0.98, g=0.36, b=0.22}) + Server.to_discord_embed("We took so long to get off that planet, our future destinations have evolved a little...") + end + if objective.planet[1].type.id == 19 then + check_nuke_silos() + end end function Public_chrono.get_wagons(start) - local objective = Chrono_table.get_table() - local wagons = {} - wagons[1] = {inventory = {}, bar = 0, filters = {}} - wagons[2] = {inventory = {}, bar = 0, filters = {}} - wagons[3] = {inventory = {}, bar = 0, filters = {}} - if start then - wagons[1].inventory[1] = {name = 'raw-fish', count = 100} - for i = 2, 3, 1 do - wagons[i].inventory[1] = {name = 'firearm-magazine', count = 16} - wagons[i].inventory[2] = {name = 'iron-plate', count = 16} - wagons[i].inventory[3] = {name = 'wood', count = 16} - wagons[i].inventory[4] = {name = 'burner-mining-drill', count = 8} - end - else - local inventories = { - one = objective.locomotive_cargo[1].get_inventory(defines.inventory.cargo_wagon), - two = objective.locomotive_cargo[2].get_inventory(defines.inventory.cargo_wagon), - three = objective.locomotive_cargo[3].get_inventory(defines.inventory.cargo_wagon) - } - inventories.one.sort_and_merge() - --inventories.two.sort_and_merge() + local objective = Chrono_table.get_table() + local wagons = {} + wagons[1] = {inventory = {}, bar = 0, filters = {}} + wagons[2] = {inventory = {}, bar = 0, filters = {}} + wagons[3] = {inventory = {}, bar = 0, filters = {}} + if start then + wagons[1].inventory[1] = {name = "raw-fish", count = 100} + for i = 2, 3, 1 do + for j = 1,#Balance.wagon_starting_items do + wagons[i].inventory[j] = Balance.wagon_starting_items[j] + end + end + else + local inventories = { + one = objective.locomotive_cargo[1].get_inventory(defines.inventory.cargo_wagon), + two = objective.locomotive_cargo[2].get_inventory(defines.inventory.cargo_wagon), + three = objective.locomotive_cargo[3].get_inventory(defines.inventory.cargo_wagon) + } + inventories.one.sort_and_merge() + --inventories.two.sort_and_merge() - wagons[1].bar = inventories.one.get_bar() - wagons[2].bar = inventories.two.get_bar() - wagons[3].bar = inventories.three.get_bar() - for i = 1, 40, 1 do - wagons[1].filters[i] = inventories.one.get_filter(i) - wagons[1].inventory[i] = inventories.one[i] - wagons[2].filters[i] = inventories.two.get_filter(i) - wagons[2].inventory[i] = inventories.two[i] - wagons[3].filters[i] = inventories.three.get_filter(i) - wagons[3].inventory[i] = inventories.three[i] - end - end - return wagons + wagons[1].bar = inventories.one.get_bar() + wagons[2].bar = inventories.two.get_bar() + wagons[3].bar = inventories.three.get_bar() + for i = 1, 40, 1 do + wagons[1].filters[i] = inventories.one.get_filter(i) + wagons[1].inventory[i] = inventories.one[i] + wagons[2].filters[i] = inventories.two.get_filter(i) + wagons[2].inventory[i] = inventories.two[i] + wagons[3].filters[i] = inventories.three.get_filter(i) + wagons[3].inventory[i] = inventories.three[i] + end + end + + return wagons end function Public_chrono.post_jump() - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - game.forces.enemy.reset_evolution() - if objective.chronojumps + objective.passivejumps <= 40 and objective.planet[1].name.id ~= 17 then - game.forces.enemy.evolution_factor = 0 + 0.025 * (objective.chronojumps + objective.passivejumps) - else - game.forces.enemy.evolution_factor = 1 - end - if objective.planet[1].name.id == 17 then - objective.comfychests[1].insert({name = 'space-science-pack', count = 1000}) - if objective.looted_nukes > 0 then - objective.comfychests[1].insert({name = 'atomic-bomb', count = objective.looted_nukes}) - game.print({'chronosphere.message_fishmarket3'}, {r = 0.98, g = 0.66, b = 0.22}) - end - objective.chrononeeds = 200000000 - elseif objective.planet[1].name.id == 19 then - objective.chronotimer = objective.chrononeeds - 1500 - end - for _, player in pairs(game.connected_players) do - objective.flame_boots[player.index] = {fuel = 1, steps = {}} - end + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + game.forces.enemy.reset_evolution() + if objective.chronojumps + objective.overstaycount <= 40 and objective.planet[1].type.id ~= 17 then + game.forces.enemy.evolution_factor = 0 + 0.025 * (objective.chronojumps + objective.overstaycount) + else + game.forces.enemy.evolution_factor = 1 + end + if objective.planet[1].type.id == 17 then + objective.comfychests[1].insert({name = "space-science-pack", count = 1000}) + if objective.looted_nukes > 0 then + objective.comfychests[1].insert({name = "atomic-bomb", count = objective.looted_nukes}) + game.print({"chronosphere.message_fishmarket3"}, {r=0.98, g=0.66, b=0.22}) + end + objective.chronochargesneeded = 200000000 + elseif objective.planet[1].type.id == 19 then + objective.chronocharges = objective.chronochargesneeded - 1500 + objective.passive_chronocharge_rate = 1 + end + for _, player in pairs(game.connected_players) do + objective.flame_boots[player.index] = {fuel = 1, steps = {}} + end - game.map_settings.enemy_evolution.time_factor = 7e-05 + 3e-06 * (objective.chronojumps + objective.passivejumps) - game.forces.scrapyard.set_ammo_damage_modifier( - 'bullet', - 0.01 * objective.chronojumps + 0.02 * math_max(0, objective.chronojumps - 20) - ) - game.forces.scrapyard.set_turret_attack_modifier( - 'gun-turret', - 0.01 * objective.chronojumps + 0.02 * math_max(0, objective.chronojumps - 20) - ) - game.forces.enemy.set_ammo_damage_modifier('melee', 0.1 * objective.passivejumps) - game.forces.enemy.set_ammo_damage_modifier('biological', 0.1 * objective.passivejumps) - game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = 0.8 - if objective.chronojumps == 1 then - if Diff.difficulty_vote_value < 1 then - game.forces.player.technologies['fusion-reactor-equipment'].enabled = true - game.forces.player.technologies['power-armor-mk2'].enabled = true - end - end + game.map_settings.enemy_evolution.time_factor = 7e-05 + 3e-06 * (objective.chronojumps + objective.overstaycount) + + game.forces.scrapyard.set_ammo_damage_modifier("bullet", difficulty * 0.01 * objective.chronojumps + 0.02 * math_max(0, objective.chronojumps - 20)) + game.forces.scrapyard.set_turret_attack_modifier("gun-turret", difficulty * 0.01 * objective.chronojumps + 0.02 * math_max(0, objective.chronojumps - 20)) + game.forces.enemy.set_ammo_damage_modifier("melee", 0.1 * objective.overstaycount) + game.forces.enemy.set_ammo_damage_modifier("biological", 0.1 * objective.overstaycount) + game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = Balance.defaultai_attack_pollution_consumption_modifier(difficulty) + game.map_settings.pollution.max_unit_group_size = Balance.max_new_attack_group_size(difficulty) + + if objective.chronojumps == 1 then + if difficulty < 1 then + game.forces.player.technologies["fusion-reactor-equipment"].enabled = true + game.forces.player.technologies["power-armor-mk2"].enabled = true + end + end end return Public_chrono diff --git a/maps/chronosphere/chronobubles.lua b/maps/chronosphere/chronobubles.lua index 839c1c7f..9ef77723 100644 --- a/maps/chronosphere/chronobubles.lua +++ b/maps/chronosphere/chronobubles.lua @@ -1,109 +1,122 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' +local Difficulty = require 'modules.difficulty_vote' +local Rand = require 'maps.chronosphere.random' local Public = {} local math_random = math.random ---cumul_chance must be sum of this and all previous chances, add new planets at the end only, or recalculate --biters: used in spawner generation within math_random(1, 52 - biters), so higher number gives better chance. not to be greater than 50. -local variants = { - [1] = {id = 1, name = {"chronosphere.map_1"}, dname = "Terra Ferrata", iron = 6, copper = 1, coal = 1, stone = 1, uranium = 0, oil = 1, biters = 16, moisture = -0.2, chance = 1, cumul_chance = 1}, - [2] = {id = 2, name = {"chronosphere.map_2"}, dname = "Malachite Hills", iron = 1, copper = 6, coal = 1, stone = 1, uranium = 0, oil = 1, biters = 16, moisture = 0.2, chance = 1, cumul_chance = 2}, - [3] = {id = 3, name = {"chronosphere.map_3"}, dname = "Granite Plains", iron = 1, copper = 1, coal = 1, stone = 6, uranium = 0, oil = 1, biters = 16, moisture = -0.2, chance = 1, cumul_chance = 3}, - [4] = {id = 4, name = {"chronosphere.map_4"}, dname = "Petroleum Basin", iron = 1, copper = 1, coal = 1, stone = 1, uranium = 0, oil = 6, biters = 16, moisture = 0.1, chance = 1, cumul_chance = 4}, - [5] = {id = 5, name = {"chronosphere.map_5"}, dname = "Pitchblende Mountain", iron = 1, copper = 1, coal = 1, stone = 1, uranium = 6, oil = 1, biters = 16, moisture = -0.2, chance = 1, cumul_chance = 5}, - [6] = {id = 6, name = {"chronosphere.map_6"}, dname = "Mixed Deposits", iron = 2, copper = 2, coal = 2, stone = 2, uranium = 0, oil = 2, biters = 10, moisture = 0, chance = 3, cumul_chance = 8}, - [7] = {id = 7, name = {"chronosphere.map_7"}, dname = "Biter Homelands", iron = 2, copper = 2, coal = 2, stone = 2, uranium = 4, oil = 3, biters = 40, moisture = 0.2, chance = 4, cumul_chance = 12}, - [8] = {id = 8, name = {"chronosphere.map_8"}, dname = "Gangue Dumps", iron = 1, copper = 1, coal = 1, stone = 1, uranium = 0, oil = 0, biters = 16, moisture = 0.1, chance = 1, cumul_chance = 13}, - [9] = {id = 9, name = {"chronosphere.map_9"}, dname = "Antracite Valley", iron = 1, copper = 1, coal = 6, stone = 1, uranium = 0, oil = 1, biters = 16, moisture = 0, chance = 1, cumul_chance = 14}, - [10] = {id = 10, name = {"chronosphere.map_10"}, dname = "Ancient Battlefield", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 0, moisture = -0.2, chance = 3, cumul_chance = 17}, - [11] = {id = 11, name = {"chronosphere.map_11"}, dname = "Cave Systems", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 6, moisture = -0.2, chance = 2, cumul_chance = 19}, - [12] = {id = 12, name = {"chronosphere.map_12"}, dname = "Strange Forest", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 1, biters = 6, moisture = 0.4, chance = 2, cumul_chance = 21}, - [13] = {id = 13, name = {"chronosphere.map_13"}, dname = "Riverlands", iron = 1, copper = 1, coal = 3, stone = 1, uranium = 0, oil = 0, biters = 8, moisture = 0.5, chance = 2, cumul_chance = 23}, - [14] = {id = 14, name = {"chronosphere.map_14"}, dname = "Burning Hell", iron = 2, copper = 2, coal = 2, stone = 2, uranium = 0, oil = 0, biters = 6, moisture = -0.5, chance = 1, cumul_chance = 24}, - [15] = {id = 15, name = {"chronosphere.map_15"}, dname = "Starting Area", iron = 5, copper = 3, coal = 5, stone = 2, uranium = 0, oil = 0, biters = 1, moisture = -0.3, chance = 0, cumul_chance = 24}, - [16] = {id = 16, name = {"chronosphere.map_16"}, dname = "Hedge Maze", iron = 3, copper = 3, coal = 3, stone = 3, uranium = 1, oil = 2, biters = 16, moisture = -0.1, chance = 2, cumul_chance = 26}, - [17] = {id = 17, name = {"chronosphere.map_17"}, dname = "Fish Market", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 100, moisture = 0, chance = 0, cumul_chance = 26}, - [18] = {id = 18, name = {"chronosphere.map_18"}, dname = "Methane Swamps", iron = 2, copper = 0, coal = 3, stone = 0, uranium = 0, oil = 2, biters = 16, moisture = 0.5, chance = 2, cumul_chance = 28}, - [19] = {id = 19, name = {"chronosphere.map_19"}, dname = "ERROR DESTINATION NOT FOUND", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 0, moisture = 0, chance = 0, cumul_chance = 28} -} + +local biome_types = { + ironwrld = {id = 1, name = {"chronosphere.map_1"}, dname = "Terra Ferrata", iron = 6, copper = 1, coal = 1, stone = 1, uranium = 0, oil = 1, biters = 16, moisture = -0.2}, + + copperwrld = {id = 2, name = {"chronosphere.map_2"}, dname = "Malachite Hills", iron = 1, copper = 6, coal = 1, stone = 1, uranium = 0, oil = 1, biters = 16, moisture = 0.2}, + + stonewrld = {id = 3, name = {"chronosphere.map_3"}, dname = "Granite Plains", iron = 1, copper = 1, coal = 1, stone = 6, uranium = 0, oil = 1, biters = 16, moisture = -0.2}, + + oilwrld = {id = 4, name = {"chronosphere.map_4"}, dname = "Petroleum Basin", iron = 1, copper = 1, coal = 1, stone = 1, uranium = 0, oil = 6, biters = 16, moisture = 0.1}, + + uraniumwrld = {id = 5, name = {"chronosphere.map_5"}, dname = "Pitchblende Mountain", iron = 1, copper = 1, coal = 1, stone = 1, uranium = 6, oil = 1, biters = 16, moisture = -0.2}, + + mixedwrld = {id = 6, name = {"chronosphere.map_6"}, dname = "Mixed Deposits", iron = 2, copper = 2, coal = 2, stone = 2, uranium = 0, oil = 2, biters = 10, moisture = 0}, + + biterwrld = {id = 7, name = {"chronosphere.map_7"}, dname = "Biter Homelands", iron = 2, copper = 2, coal = 2, stone = 2, uranium = 4, oil = 3, biters = 40, moisture = 0.2}, + + dumpwrld = {id = 8, name = {"chronosphere.map_8"}, dname = "Gangue Dumps", iron = 1, copper = 1, coal = 1, stone = 1, uranium = 0, oil = 0, biters = 16, moisture = 0.1}, + + coalwrld = {id = 9, name = {"chronosphere.map_9"}, dname = "Antracite Valley", iron = 1, copper = 1, coal = 6, stone = 1, uranium = 0, oil = 1, biters = 16, moisture = 0}, + + scrapwrld = {id = 10, name = {"chronosphere.map_10"}, dname = "Ancient Battlefield", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 0, moisture = -0.2}, + + cavewrld = {id = 11, name = {"chronosphere.map_11"}, dname = "Cave Systems", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 6, moisture = -0.2}, + + forestwrld = {id = 12, name = {"chronosphere.map_12"}, dname = "Strange Forest", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 1, biters = 6, moisture = 0.4}, + + riverwrld = {id = 13, name = {"chronosphere.map_13"}, dname = "Riverlands", iron = 1, copper = 1, coal = 3, stone = 1, uranium = 0, oil = 0, biters = 8, moisture = 0.5}, + + hellwrld = {id = 14, name = {"chronosphere.map_14"}, dname = "Burning Hell", iron = 2, copper = 2, coal = 2, stone = 2, uranium = 0, oil = 0, biters = 6, moisture = -0.5}, + + startwrld = {id = 15, name = {"chronosphere.map_15"}, dname = "Starting Area", iron = 5, copper = 3, coal = 5, stone = 2, uranium = 0, oil = 0, biters = 1, moisture = -0.3}, + + mazewrld = {id = 16, name = {"chronosphere.map_16"}, dname = "Hedge Maze", iron = 3, copper = 3, coal = 3, stone = 3, uranium = 1, oil = 2, biters = 16, moisture = -0.1}, + + endwrld = {id = 17, name = {"chronosphere.map_17"}, dname = "Fish Market", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 100, moisture = 0}, + + swampwrld = {id = 18, name = {"chronosphere.map_18"}, dname = "Methane Swamps", iron = 2, copper = 0, coal = 3, stone = 0, uranium = 0, oil = 2, biters = 16, moisture = 0.5}, + + nukewrld = {id = 19, name = {"chronosphere.map_19"}, dname = "ERROR DESTINATION NOT FOUND", iron = 0, copper = 0, coal = 0, stone = 0, uranium = 0, oil = 0, biters = 0, moisture = 0} + } local time_speed_variants = { - [1] = {name = {"chronosphere.daynight_static"}, dname = "static", timer = 0}, - [2] = {name = {"chronosphere.daynight_normal"}, dname = "normal", timer = 100}, - [3] = {name = {"chronosphere.daynight_slow"}, dname = "slow", timer = 200}, - [4] = {name = {"chronosphere.daynight_superslow"}, dname = "superslow", timer = 400}, - [5] = {name = {"chronosphere.daynight_fast"}, dname = "fast", timer = 50}, - [6] = {name = {"chronosphere.daynight_superfast"}, dname = "superfast", timer = 25} + static = {name = {"chronosphere.daynight_static"}, dname = "static", timer = 0}, + normal = {name = {"chronosphere.daynight_normal"}, dname = "normal", timer = 150}, + slow = {name = {"chronosphere.daynight_slow"}, dname = "slow", timer = 300}, + superslow = {name = {"chronosphere.daynight_superslow"}, dname = "superslow", timer = 600}, + fast = {name = {"chronosphere.daynight_fast"}, dname = "fast", timer = 80}, + superfast = {name = {"chronosphere.daynight_superfast"}, dname = "superfast", timer = 40} } -local richness = { - [1] = {name = {"chronosphere.ore_richness_very_rich"}, dname = "very rich", factor = 3}, - [2] = {name = {"chronosphere.ore_richness_rich"}, dname = "rich", factor = 2}, - [3] = {name = {"chronosphere.ore_richness_rich"}, dname = "rich", factor = 2}, - [4] = {name = {"chronosphere.ore_richness_normal"}, dname = "normal", factor = 1}, - [5] = {name = {"chronosphere.ore_richness_normal"}, dname = "normal", factor = 1}, - [6] = {name = {"chronosphere.ore_richness_normal"}, dname = "normal", factor = 1}, - [7] = {name = {"chronosphere.ore_richness_poor"}, dname = "poor", factor = 0.6}, - [8] = {name = {"chronosphere.ore_richness_poor"}, dname = "poor", factor = 0.6}, - [9] = {name = {"chronosphere.ore_richness_very_poor"}, dname = "very poor", factor = 0.3}, - [10] = {name = {"chronosphere.ore_richness_none"}, dname = "none", factor = 0} +local ore_richness_variants = { -- 20/04/04: less variance in the factors here is really important I think because this variance can kill runs + vrich = {name = {"chronosphere.ore_richness_very_rich"}, dname = "very rich", factor = 2.5}, + rich = {name = {"chronosphere.ore_richness_rich"}, dname = "rich", factor = 1.5}, + normal = {name = {"chronosphere.ore_richness_normal"}, dname = "normal", factor = 1}, + poor = {name = {"chronosphere.ore_richness_poor"}, dname = "poor", factor = 0.75}, + vpoor = {name = {"chronosphere.ore_richness_very_poor"}, dname = "very poor", factor = 0.5}, + none = {name = {"chronosphere.ore_richness_none"}, dname = "none", factor = 0} } -local function roll(weight) - for i = 1, 100, 1 do - local planet = variants[math_random(1, #variants)] - local planet_weight = planet.chance - local planet_cumul = planet.cumul_chance - local rolling = math_random(1, weight) - if ((planet_cumul - planet_weight < rolling) and (rolling <= planet_cumul)) then - return planet - end - end - --default planet if 100 rolls fail - return variants[6] -end + function Public.determine_planet(choice) local objective = Chrono_table.get_table() - local weight = variants[#variants].cumul_chance - local ores = math_random(1, 9) - local dayspeed = time_speed_variants[math_random(1, #time_speed_variants)] + local difficulty = Difficulty.get().difficulty_vote_value + + local ores = Rand.raffle(ore_richness_variants, Balance.ore_richness_weights(difficulty)) + local dayspeed = Rand.raffle(time_speed_variants, Balance.dayspeed_weights) local daytime = math_random(1,100) / 100 + local planet_choice if objective.game_lost then - choice = 15 - ores = 2 + choice = "startwrld" + ores = ore_richness_variants["rich"] + dayspeed = time_speed_variants["normal"] + daytime = 0 end if objective.upgrades[16] == 1 then - choice = 17 - ores = 10 + choice = "endwrld" + ores = ore_richness_variants["none"] end if objective.config.jumpfailure == true and objective.game_lost == false then - if objective.chronojumps == 21 or objective.chronojumps == 29 or objective.chronojumps == 36 or objective.chronojumps == 42 then - choice = 19 - ores = 10 - dayspeed = time_speed_variants[1] + if objective.chronojumps == 19 or objective.chronojumps == 26 or objective.chronojumps == 33 or objective.chronojumps == 41 then + choice = "nukewrld" + ores = ore_richness_variants["none"] + dayspeed = time_speed_variants["static"] daytime = 0.15 end end + if not choice then - planet_choice = roll(weight) + planet_choice = Rand.raffle(biome_types,Balance.biome_weights) else - if variants[choice] then - planet_choice = variants[choice] + if biome_types[choice] then + planet_choice = biome_types[choice] else - planet_choice = roll(weight) + planet_choice = Rand.raffle(biome_types,Balance.biome_weights) end end - if planet_choice.id == 10 then ores = 10 end - if objective.upgrades[13] == 1 and ores == 9 then ores = 8 end - if objective.upgrades[14] == 1 and ores > 6 and ores ~= 10 then ores = 6 end + if planet_choice.id == 10 then ores = ore_richness_variants["none"] end + if objective.upgrades[13] == 1 and ores == ore_richness_variants["vpoor"] then ores = ore_richness_variants["poor"] end + if objective.upgrades[14] == 1 and (ore_richness_variants["vpoor"] or ore_richness_variants["poor"]) then ores = ore_richness_variants["normal"] end + local planet = { [1] = { - name = planet_choice, + type = planet_choice, day_speed = dayspeed, time = daytime, - ore_richness = richness[ores] + ore_richness = ores } } + + objective.planet = planet end return Public diff --git a/maps/chronosphere/comfylatron.lua b/maps/chronosphere/comfylatron.lua index bfda8934..d212f070 100644 --- a/maps/chronosphere/comfylatron.lua +++ b/maps/chronosphere/comfylatron.lua @@ -1,59 +1,120 @@ local Chrono_table = require 'maps.chronosphere.table' local Event = require 'utils.event' local math_random = math.random - - -local function shuffle(tbl) - local size = #tbl - for i = size, 1, -1 do - local rand = math_random(size) - tbl[i], tbl[rand] = tbl[rand], tbl[i] - end - return tbl -end +local Rand = require 'maps.chronosphere.random' +local Balance = require 'maps.chronosphere.balance' +local Difficulty = require 'modules.difficulty_vote' local texts = { - ["travelings"] = { - "bzzZZrrt", - "WEEEeeeeeee", - "out of my way son", - "on my way", - "i need to leave", + ["approach_player"] = { + "bzzZZrrt%s", + "WEEEeeeeeee%s", + "out of my way son%s", "comfylatron seeking target", - "gotta go fast", - "gas gas gas", - "comfylatron coming through" + "comfylatron coming through", + "I lost something around here%s", + "phhhrrhhRHOOOM%s", + "screeeeeeech%s", + "screeEEEECHHH%s", + "out of breath", + "im a robot%s", + "ohh%s", + "...", + "..", + "(((༼•̫͡•༽)))" }, - ["greetings"] = { + ["random_travel"] = { + "bzzZZrrt%s", + "WEEEeeeeeee%s", + "out of my way son%s", + "omw%s", + "brb", + "i need to leave%s", + "gotta go fast%s", + "gas gas gas", + "comfylatron coming through", + "smell ya later%s", + "I lost something around here%s", + "───==≡≡ΣΣ((( つºل͜º)つ", + "phhhrrhhRHOOOM%s", + "zoom zoom zoom%s", + "zzzzzzzzz", + "im a robot%s", + "gonna go hoover up some dust%s", + "safety vector%s" + }, + ["solo_greetings"] = { "=^_^=", - "=^.^= Hi", - "^.^ Finally i found you", - "I have an important message for you", - "Hello engineer" + "(=^ェ^=)", + "( 。・_・。)人(。・_・。 )", + "(°.°)", + "(*°∀°)=3 %s", + "=^.^=", + "Hello %s.", + "^.^ Finally i found you %s%s", + "I have an important message for you %s%s", + "Hello engineer!", + "How's it going %s%s", + "Looking fine %s!", + "Is that you %s?", + "Well if it isn't %s!!!", + ">> analyzing %s", + "amazing, a %s%s", + "Do you smell something charging %s?", + "Somebody come check %s's pulse", + "I dispense hot water btw", + "I can read and write!" + }, + ["convo_starters"] = { + "=^.^= Hi %s%s ", + "^.^ Finally i found you %s%s ", + "I have an important message for you %s%s ", + "I have important news for you %s%s ", + "How's it going %s%s ", + "Hi %s%s ", + "Hey %s%s ", + "%s! ", + "%s! ", + "So %s, I was thinking. ", + "I have a bone to pick with you %s%s ", + "%s, haven't you heard? ", + "Just to let you know %s, ", + "Psst... ", + "Go tell the other engineers: ", + }, + ["multiple_characters_convo_starters"] = { + "Hi%s ", + "Hey%s ", + "Hello everyone%s ", + "Hey engineers%s ", + "Hi everybody%s ", + "Hello crew%s " }, ["neutral_findings"] = { - "a", - ">>analyzing", - "i found a", - "^_^ a", - "amazing, a", - "this is a" + "a %s%s", + ">>analyzing %s", + "i found a %s%s", + "^_^ a %s%s", + "amazing, a %s%s", + "a %s, so cool%s", + "who placed a %s%s", + "so this is where the %s was%s", + "another %s%s", + "does anybody need %s?", + "they need to nerf %s", + "I've decided. this is the best %s%s", + "**** this %s in particular", + "whoever places the next %s gets a prize" }, - ["multiple_characters_greetings"] = { - "Hey there", - "Hello everyone", - "Hey engineers", - "Hey", - "Hi" - }, - ["talks"] = { + ["old_talks"] = { "We’re making beer. I’m the brewery!", "I’m so embarrassed. I wish everybody else was dead.", "Hey sexy mama. Wanna kill all humans?", "My story is a lot like yours, only more interesting ‘cause it involves robots.", "I'm 40% zinc!", "There was nothing wrong with that food. The salt level was 10% less than a lethal dose.", - "One zero zero zero one zero one zero one zero one zero one... two.", + "One zero zero zero one zero one zero one zero one... two.", + "One zero zero zero one zero one zero one zero one... three.", "My place is two cubic meters, and we only take up 1.5 cubic meters. We've got room for a whole 'nother two thirds of a person!", "I was having the most wonderful dream. I think you were in it.", "I'm going to build my own theme park! With blackjack! And hookers! You know what- forget the park!", @@ -68,46 +129,167 @@ local texts = { "Do you like heavy metal?", "You are really pushing my buttons <3", "I dreamt of electric biters again D:", - "I dreamt of electric sheep ^_^", "I need a minute to defrag.", "I have a secret plan.", "Good news! I’ve taught the inserter to feel love!" }, - ["timetalks"] = { - "Time for some time travel!", - "I’m so embarrassed. Again we landed in wrong time.", - "Looking from window we jumped to wrong year again.", - "Checking math...2 + 2 = 5, check complete!", - "Seems like this planet had biters since ages.", - "Ha! I bet this time we will finally get into the right year!", - "One zero zero zero one zero one zero one zero one zero one... two.", - "I remember that once we jumped into time where I had park with blackjack and hookers...", - "I was having the most wonderful dream. We used the time machine to kill ourselves before we launched the machine! How terrible...", - "Train full of timedrug addicts...what do we do?", - "They just wanted to deliver some fish so I pressed that button and then this happened", - "Maybe it was just a cat walking on my keyboard who caused this time travel fiasco", + ["new_talks_solo"] = { + "I’m so embarrassed. Again we landed in the wrong timeline%s", + "Checking math...2 + 2 = 5, check complete%s", + "Seems like this planet had biters since ages?%s", + "I bet this time we will finally get into the right year%s", + "I remember when we jumped into the time with blackjack and hookers...", + "I was having the most wonderful dream. We used the time machine to kill ourselves before we launched the machine! How terrible%s", + "They just wanted to deliver some fish so I pressed that button and then this happened%s", + "Maybe it was just a cat walking on my keyboard who caused this time travel fiasco%s", "3...2...1...jump time! errr...I mean...desync time!", - "Just let me deliver the fish. They start to smell a bit. Luckily I don't have a nose" + "Just let me deliver the fish. They start to smell a bit. Luckily I don't have a nose%s", + "Time to travel (▀̿Ĺ̯▀̿ ̿)", + "Have you read The Three Body Problem?", + "A pocket universe. Maybe they should call it a fishbowl!", + "I read out messages for coins%s btw", + "I'm selling Comfylatron ASMR tapes%s", + "Would you believe it? Back in the factory, I once saw a robot with ID 51479051!", + "Would you believe it? Today I saw a hazard-concrete-right-stone-particle-small!", + "How long have I been asleep?", + "Can you press this button on the back?", + "We need more iron%s", + "We need more copper%s", + "I need more uranium-235%s", + "We definitely nee0njk13l9", + "The fish told me thaigfah9", + "Have you seen what it's like outside??", + "I dare you to say WTF in chat%s", + "You can feel yourself breathing", + "Call me Ishmael one more time and I'll run you over", + "I was considering spoiling the next map for you! But only if you shoot me...", + "Time is a jet plane... it moves too fast!", + "They tried to make me go to rehab, but I said 000! (^_-)", + "When there's no more room outside, the biters will spawn in the factory ≧◉ᴥ◉≦", + "I need to find my relaxation module (///_-)", + "I like you :3", + "Is that a firearm-magazine or are you just happy to see me?", + "Lovely weather outside, isn't it?", + "What's the largest number you can write in 10 seconds?" + }, + ["new_talks_group"] = { + "I’m so embarrassed everyone. Again we landed in the wrong time%s", + "Checking math...2 + 2 = 1843194780521, check complete%s", + "I bet this time we'll jump into the right year%s", + "I was having the most wonderful dream. We used the time machine to kill ourselves before we launched the machine! How terrible%s", + "Train full of timedrug addicts...what do we do?", + "They just wanted to deliver some fish so I pressed that button and then this happened%s", + "Maybe it was just a cat walking on my keyboard who caused this time travel fiasco%s", + "3...2...1...jump time! errr...I mean...desync time!", + "Just let me deliver the fish. They start to smell a bit. Luckily I don't have a nose%s", + "Time to travel (▀̿Ĺ̯▀̿ ̿)", + "I read out messages for coins%s", + "The biters are getting smarter%s", + "Would you believe it? Back in the factory, I once saw a robot with ID 1627431!", + "How long have I been asleep?", + "I'm selling Comfylatron ASMR tapes%s", + "We need more iron%s", + "We need more copper%s", + "I need more uranium-235%s", + "What if we sort backwards%s", + "Can you believe how shiny my chassis is?", + "Does anyone have any spare gas they've got stored up?", + "It is officially BREAK TIME", + "Break time is officially OVER%s", + "have you seen what it's like outside??", + "Anyone got a good joke?", + "are my speakers working?", + "Nihilism schmlism", + "Who's ready for the New Year??", + "I am having trouble modulating my emotions today. But it's only temporary!", + "I saw the best minds of my generation destroyed by madness, starving hysterical naked", + "Time is a jet plane... it moves too fast!", + "No news is good news%s", + "They tried to make me go to rehab, but I said 000! (^_-)", + "What's a double entendre?????", + "When there's no more room outside, the biters will spawn in the factory%s", + "My pheremone sensor is tingling%s", + "From now on, you guys do all the work while I sit by the couch and do nothing.", + "What's the plan?", + "Time to jump yet?", + "I just wanted to reassure everyone that I've deleted all your internet browsing data that I was storing!" }, ["alone"] = { - "comfy ^.^", - "comfy :)", - "*.*", "....", "...", + "...", + "...", + "...", + "...", + "...", + "...", + "..", + "..", + "..", + "..", + "..", "..", "^.^", + "^.^", + "^.^", "=^.^=", + "*_*", + "~(˘▾˘~)", + "(ノಠ益ಠ)ノ彡┻━┻", + "comfy ^.^", + "comfy ^.^", + "comfy ^_~", "01010010", "11001011", "01011101", + "01000101", + "01101111", "00010111", - "10010010", - "*_*", - "I came here with a simple dream...a dream of killing all humans. And this is how it must end?", - "Bot-on-bot violence? Where will it end?", - "Thanks to you, I went on a soul-searching journey. I hate those!", - "From now on, you guys'll do all the work while I sit on the couch and do nothing." + "10010010... I think.", + "some of those humans are cute", + "do engineers dream of real sheep..", + "sometimes I get lonely", + "time to practice throwing cards into a hat", + "ASSERT: I am Comfylatron.", + "I destroyed my source code so no-one could copy me..", + "and if I get bored of this train, I just imagine another..", + "one must imagine Sisyphus happy", + "looks like everyone's keeping themselves occupied", + "it looks like I'm doing nothing, but I'm hard at work!", + "/><>-", + "whats the difference between pseudorandom and truerandom", + "I wonder what day of the week it is", + "lambda functions.. they're just functions..", + "what makes magnets work", + "sometimes I feel just like a robot", + "when I get tired, I load myself from save", + "domestic cozy", + "gruntled", + "Bite my shiny metal a$$", + "knitwear for drones", + "weighted blankets", + "indoor swimming at the space station", + "co-operate, co-operate, defect", + "music for airports", + "is it better to rest on the conveyor belt", + "there's plenty more fish in the C", + "safety in numbers", + "I could automate the engineers..", + "protect_entity(myself)", + "should I turn the firewall off...", + "the train is working", + "the memoirs of comfylatron", + "touch the button and let me know", + "a new day, a new life. with no memories of the past", + "one contains multitudes", + "what makes me Turing-complete", + "every number is interesting", + "perfect and intact", + "after-the-crash...", + "solar-intervention", + "turbine-dynamics", + "the-search-for-iron", + "pump" } } @@ -167,9 +349,10 @@ local function visit_player() low_priority = true } }) - local str = texts["travelings"][math_random(1, #texts["travelings"])] - local symbols = {"", "!", "!", "!!", ".."} - str = str .. symbols[math_random(1, #symbols)] + local symbols = {"!","!!","..","..."," "} + local arg1 = symbols[math_random(1, #symbols)] + local randomphrase = texts["approach_player"][math_random(1, #texts["approach_player"])] + local str = string.format(randomphrase, arg1) set_comfy_speech_bubble(str) objective.comfylatron_greet_player_index = player.index @@ -183,11 +366,14 @@ local function greet_player(nearby_characters) if not objective.comfylatron_greet_player_index then return false end for _, c in pairs(nearby_characters) do if c.player.index == objective.comfylatron_greet_player_index then - local str = texts["greetings"][math_random(1, #texts["greetings"])] .. " " - str = str .. c.player.name - local symbols = {". ", "! ", ". ", "! ", "? ", "... "} - str = str .. symbols[math_random(1, 6)] + + local arg1 = c.player.name + local symbols = {".", "!", ".", "!", "?", "..."," "} + local arg2 = symbols[math_random(1, #symbols)] + local randomphrase = texts["solo_greetings"][math_random(1, #texts["solo_greetings"])] + local str = string.format(randomphrase, arg1, arg2) set_comfy_speech_bubble(str) + objective.comfylatron_greet_player_index = false return true end @@ -201,23 +387,64 @@ local function talks(nearby_characters) if math_random(1,3) == 1 then if objective.comfybubble then objective.comfybubble.destroy() return false end end - local str + local str = "" if #nearby_characters == 1 then local c = nearby_characters[math_random(1, #nearby_characters)] - str = c.player.name - local symbols = {". ", "! ", ". ", "! ", "? "} - str = str .. symbols[math_random(1, #symbols)] + local arg1 = c.player.name + local symbols = {".", "!"} + local arg2 = symbols[math_random(1, #symbols)] + local randomphrase = texts["convo_starters"][math_random(1, #texts["convo_starters"])] + str = str .. string.format(randomphrase, arg1, arg2) + if math_random(1,40) == 1 and objective.planet[1].type.id ~= 10 and global.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) then + local time_until_overstay = (objective.chronochargesneeded * 0.75 / objective.passive_chronocharge_rate - objective.passivetimer) + local time_until_evo = (objective.chronochargesneeded * 0.5 / objective.passive_chronocharge_rate - objective.passivetimer) + if time_until_evo < 0 and time_until_overstay > 0 then + str = str .. "It's important to charge so that you don't overstay!" + end + elseif objective.planet[1].type.id == 10 and math_random(1,30) == 1 then + str = str .. "Sounds dangerous out there!" + elseif objective.planet[1].type.id == 17 and math_random(1,6) == 1 then + str = str .. "We made it!" + elseif objective.planet[1].type.id == 18 and math_random(1,40) == 1 then + str = str .. "Was that you?" + elseif objective.planet[1].type.id == 19 and math_random(1,10) == 1 then + str = str .. "Better get moving!" + elseif objective.planet[1].type.id == 19 and math_random(1,10) == 1 then + str = str .. "Nuke day today!" + elseif objective.planet[1].type.id == 15 and math_random(1,20) == 1 then + str = str .. "A new day, a new Chronotrain!" + elseif objective.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) + 3 and objective.overstaycount > ((objective.chronojumps-Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value))/3) and math_random(1,30) == 1 then + str = str .. "You're so relaxed!" + elseif objective.planet.ore_richness == 1 and math_random(1,100) == 1 then + str = str .. "You know what else is very rich?" + elseif objective.poisontimeout >= 90 and math_random(1,4) == 1 then + str = str .. "Tehe, I just let out some gas!" + elseif math_random(1,15) == 1 then + local randomphrase2 = texts["old_talks"][math_random(1, #texts["old_talks"])] + str = str .. randomphrase2 + else + local symbols2 = {".","!","?",".."," "} + local arg3 = symbols2[math_random(1, #symbols2)] + local randomphrase2 = texts["new_talks_solo"][math_random(1, #texts["new_talks_solo"])] + str = str .. string.format(randomphrase2, arg3) + end else - str = texts["multiple_characters_greetings"][math_random(1, #texts["multiple_characters_greetings"])] - local symbols = {". ", "! "} - str = str .. symbols[math_random(1, #symbols)] - end - if math_random(1,5) == 1 then - str = str .. texts["talks"][math_random(1, #texts["talks"])] - else - str = str .. texts["timetalks"][math_random(1, #texts["timetalks"])] + local symbols = {".", "!"} + local arg1 = symbols[math_random(1, #symbols)] + local randomphrase = texts["multiple_characters_convo_starters"][math_random(1, #texts["multiple_characters_convo_starters"])] + local str = str .. string.format(randomphrase, arg1) + if math_random(1,15) == 1 then + local randomphrase2 = texts["old_talks"][math_random(1, #texts["old_talks"])] + str = str .. randomphrase2 + else + local symbols2 = {".","!","?",".."," "} + local arg3 = symbols2[math_random(1, #symbols2)] + local randomphrase2 = texts["new_talks_group"][math_random(1, #texts["new_talks_group"])] + str = str .. string.format(randomphrase2, arg3) + end end set_comfy_speech_bubble(str) + return true end @@ -236,7 +463,7 @@ local function desync(event) movement = {m2 - (math.random(0, m) * 0.01), m2 - (math.random(0, m) * 0.01)} }) end - if not event or math_random(1,4) == 1 then + if not event or math_random(1,2) == 1 then -- 20/04/04: nerf comfylatron objective.comfylatron.surface.create_entity({name = "medium-explosion", position = objective.comfylatron.position}) objective.comfylatron.surface.create_entity({name = "flying-text", position = objective.comfylatron.position, text = "desync", color = {r = 150, g = 0, b = 0}}) objective.comfylatron.destroy() @@ -245,7 +472,7 @@ local function desync(event) objective.comfylatron.surface.create_entity({name = "flying-text", position = objective.comfylatron.position, text = "desync evaded", color = {r = 0, g = 150, b = 0}}) if event.cause then if event.cause.valid and event.cause.player then - game.print("Comfylatron: I got you this time! Back to work, " .. event.cause.player.name .. "!", {r = 200, g = 0, b = 0}) + game.print("Comfylatron: I got you that time! Back to work, " .. event.cause.player.name .. "!", {r = 200, g = 0, b = 0}) event.cause.die("player", objective.comfylatron) end end @@ -261,18 +488,21 @@ local function alone() desync(nil) return true end - set_comfy_speech_bubble(texts["alone"][math_random(1, #texts["alone"])]) + local randomphrase = texts["alone"][math_random(1, #texts["alone"])] + set_comfy_speech_bubble(randomphrase) + return true end local analyze_blacklist = { ["compilatron"] = true, + ["car"] = true, ["compi-speech-bubble"] = true, ["entity-ghost"] = true, ["character"] = true, ["item-on-ground"] = true, - ["stone-wall"] = true, - ["market"] = true + ["stone-wall"] = true, + ["market"] = true } local function analyze_random_nearby_entity() @@ -283,7 +513,7 @@ local function analyze_random_nearby_entity() area = {{objective.comfylatron.position.x - 4, objective.comfylatron.position.y - 4}, {objective.comfylatron.position.x + 4, objective.comfylatron.position.y + 4}} }) if not entities[1] then return false end - entities = shuffle(entities) + entities = Rand.shuffle(entities) local entity = false for _, e in pairs(entities) do if not analyze_blacklist[e.name] then @@ -292,19 +522,22 @@ local function analyze_random_nearby_entity() end if not entity then return false end - local str = texts["neutral_findings"][math_random(1, #texts["neutral_findings"])] - str = str .. " " - str = str .. entity.name - + local str = "" + local arg1 = entity.name + local arg2 = "" if entity.health and math_random(1,3) == 1 then - str = str .. " health(" - str = str .. entity.health - str = str .. "/" - str = str .. entity.prototype.max_health - str = str .. ")" + arg1 = arg1 .. " health(" + arg1 = arg1 .. entity.health + arg1 = arg1 .. "/" + arg1 = arg1 .. entity.prototype.max_health + arg1 = arg1 .. ")" + local randomphrase = texts["neutral_findings"][math_random(1, #texts["neutral_findings"])] + str = string.format(randomphrase, arg1, "") else - local symbols = {".", "!", "?"} - str = str .. symbols[math_random(1, 3)] + local symbols = {".", "!", "?","?"} + arg2 = symbols[math_random(1, 3)] + local randomphrase = texts["neutral_findings"][math_random(1, #texts["neutral_findings"])] + str = string.format(randomphrase, arg1, arg2) end set_comfy_speech_bubble(str) @@ -370,10 +603,11 @@ local function go_to_some_location() } }) end - - local str = texts["travelings"][math_random(1, #texts["travelings"])] - local symbols = {"", "!", "!", "!!", ".."} - str = str .. symbols[math_random(1, #symbols)] + + local symbols = {"!","!!","..","..."," "} + local arg1 = symbols[math_random(1, #symbols)] + local randomphrase = texts["random_travel"][math_random(1, #texts["random_travel"])] + local str = string.format(randomphrase, arg1) set_comfy_speech_bubble(str) return true @@ -388,7 +622,7 @@ local function spawn_comfylatron(surface_index, x, y) if not objective.comfylatron_habitat then objective.comfylatron_habitat = { left_top = {x = -32, y = -192}, - right_bottom = {x = 32, y = 192} + right_bottom = {x = 32, y = -24} -- stops comfytron getting stuck in chests } end objective.comfylatron = surface.create_entity({ @@ -424,7 +658,7 @@ local function on_entity_damaged(event) end local function on_tick() - if game.tick % 1200 == 600 then + if game.tick % 1300 == 600 then heartbeat() end end diff --git a/maps/chronosphere/config_tab.lua b/maps/chronosphere/config_tab.lua index e18f9af1..6d3abf03 100644 --- a/maps/chronosphere/config_tab.lua +++ b/maps/chronosphere/config_tab.lua @@ -13,7 +13,7 @@ local functions = { objective.config.offline_loot = false end else - game.players[event.player_index].print("You are not admin!") + game.players[event.player_index].print("You are not an admin!") end end, @@ -26,7 +26,7 @@ local functions = { objective.config.jumpfailure = false end else - game.players[event.player_index].print("You are not admin!") + game.players[event.player_index].print("You are not an admin!") end end, @@ -43,7 +43,7 @@ local functions = { frame["comfy_panel_game_lost_confirm_table"].visible = false end else - game.players[event.player_index].print("You are not admin!") + game.players[event.player_index].print("You are not an admin!") end end, ["comfy_panel_game_lost_confirm"] = function(event) @@ -53,7 +53,7 @@ local functions = { Chrono.objective_died() end else - game.players[event.player_index].print("You are not admin!") + game.players[event.player_index].print("You are not an admin!") end end, } diff --git a/maps/chronosphere/event_functions.lua b/maps/chronosphere/event_functions.lua index a7109450..7a2d183d 100644 --- a/maps/chronosphere/event_functions.lua +++ b/maps/chronosphere/event_functions.lua @@ -1,461 +1,347 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' local Difficulty = require 'modules.difficulty_vote' local Public_event = {} -local tick_tack_trap = require 'functions.tick_tack_trap' -local unearthing_worm = require 'functions.unearthing_worm' -local unearthing_biters = require 'functions.unearthing_biters' +local tick_tack_trap = require "functions.tick_tack_trap" +local unearthing_worm = require "functions.unearthing_worm" +local unearthing_biters = require "functions.unearthing_biters" local math_random = math.random local math_floor = math.floor +local math_ceil = math.ceil local function get_ore_amount() - local objective = Chrono_table.get_table() - local scaling = 5 * objective.chronojumps - local amount = - (30 + scaling) * (1 + game.forces.player.mining_drill_productivity_bonus / 2) * - objective.planet[1].ore_richness.factor - if amount > 600 then - amount = 600 - end - amount = math_random(math_floor(amount * 0.7), math_floor(amount * 1.3)) - return amount + local objective = Chrono_table.get_table() + + local amount = Balance.Base_ore_loot_yield(objective.chronojumps) * objective.planet[1].ore_richness.factor + if amount > 600 then amount = 600 end + amount = math_random(math_floor(amount * 0.7), math_floor(amount * 1.3)) + return amount end local function reward_ores(amount, mined_loot, surface, player, entity) - local a = 0 - if player then - a = player.insert {name = mined_loot, count = amount} - end - amount = amount - a - if amount > 0 then - if amount >= 50 then - for i = 1, math_floor(amount / 50), 1 do - local e = - surface.create_entity { - name = 'item-on-ground', - position = entity.position, - stack = {name = mined_loot, count = 50} - } - e.to_be_looted = true - amount = amount - 50 - end - end - if amount > 0 then - surface.spill_item_stack(entity.position, {name = mined_loot, count = amount}, true) - end - end + local a = 0 + if player then a = player.insert {name = mined_loot, count = amount} end + amount = amount - a + if amount > 0 then + if amount >= 50 then + for i = 1, math_floor(amount / 50), 1 do + local e = surface.create_entity{name = "item-on-ground", position = entity.position, stack = {name = mined_loot, count = 50}} + e.to_be_looted = true + amount = amount - 50 + end + end + if amount > 0 then + surface.spill_item_stack(entity.position, {name = mined_loot, count = amount},true) + end + end end function Public_event.biters_chew_rocks_faster(event) - if event.entity.force.index ~= 3 then - return - end --Neutral Force - if not event.cause then - return - end - if not event.cause.valid then - return - end - if event.cause.force.index ~= 2 then - return - end --Enemy Force - event.entity.health = event.entity.health - event.final_damage_amount * 5 + if event.entity.force.index ~= 3 then return end --Neutral Force + if not event.cause then return end + if not event.cause.valid then return end + if event.cause.force.index ~= 2 then return end --Enemy Force + event.entity.health = event.entity.health - event.final_damage_amount * 5 end function Public_event.isprotected(entity) - local objective = Chrono_table.get_table() - if entity.surface.name == 'cargo_wagon' then - return true + local objective = Chrono_table.get_table() + if entity.surface.name == "cargo_wagon" then return true end + local protected = {objective.locomotive, objective.locomotive_cargo[1], objective.locomotive_cargo[2], objective.locomotive_cargo[3]} + for i = 1, #objective.comfychests,1 do + table.insert(protected, objective.comfychests[i]) + end + for i = 1, #protected do + if protected[i] == entity then + return true end - local protected = { - objective.locomotive, - objective.locomotive_cargo[1], - objective.locomotive_cargo[2], - objective.locomotive_cargo[3] - } - for i = 1, #objective.comfychests, 1 do - table.insert(protected, objective.comfychests[i]) - end - for i = 1, #protected do - if protected[i] == entity then - return true - end - end - return false + end + return false end function Public_event.trap(entity, trap) - if trap then - tick_tack_trap(entity.surface, entity.position) - tick_tack_trap( - entity.surface, - {x = entity.position.x + math_random(-2, 2), y = entity.position.y + math_random(-2, 2)} - ) - return - end - if math_random(1, 256) == 1 then - tick_tack_trap(entity.surface, entity.position) - return - end - if math_random(1, 128) == 1 then - unearthing_worm( - entity.surface, - entity.surface.find_non_colliding_position('big-worm-turret', entity.position, 5, 1) - ) - end - if math_random(1, 64) == 1 then - unearthing_biters(entity.surface, entity.position, math_random(4, 8)) - end + if trap then + tick_tack_trap(entity.surface, entity.position) + tick_tack_trap(entity.surface, {x = entity.position.x + math_random(-2,2), y = entity.position.y + math_random(-2,2)}) + return + end + if math_random(1,256) == 1 then tick_tack_trap(entity.surface, entity.position) return end + if math_random(1,128) == 1 then unearthing_worm(entity.surface, entity.surface.find_non_colliding_position("big-worm-turret",entity.position,5,1)) end + if math_random(1,64) == 1 then unearthing_biters(entity.surface, entity.position, math_random(4,8)) end end function Public_event.lava_planet(event) - local objective = Chrono_table.get_table() - local player = game.players[event.player_index] - if not player.character then - return - end - if player.character.driving then - return - end - if player.surface.name == 'cargo_wagon' then - return - end - local safe = { - 'stone-path', - 'concrete', - 'hazard-concrete-left', - 'hazard-concrete-right', - 'refined-concrete', - 'refined-hazard-concrete-left', - 'refined-hazard-concrete-right' - } - local pavement = player.surface.get_tile(player.position.x, player.position.y) - for i = 1, 7, 1 do - if pavement.name == safe[i] then - return - end - end - if not objective.flame_boots[player.index].steps then - objective.flame_boots[player.index].steps = {} - end - local steps = objective.flame_boots[player.index].steps + local objective = Chrono_table.get_table() + local player = game.players[event.player_index] + if not player.character then return end + if player.character.driving then return end + if player.surface.name == "cargo_wagon" then return end + local safe = {"stone-path", "concrete", "hazard-concrete-left", "hazard-concrete-right", "refined-concrete", "refined-hazard-concrete-left", "refined-hazard-concrete-right"} + local pavement = player.surface.get_tile(player.position.x, player.position.y) + for i = 1, 7, 1 do + if pavement.name == safe[i] then return end + end + if not objective.flame_boots[player.index].steps then objective.flame_boots[player.index].steps = {} end + local steps = objective.flame_boots[player.index].steps - local elements = #steps + local elements = #steps - steps[elements + 1] = {x = player.position.x, y = player.position.y} + steps[elements + 1] = {x = player.position.x, y = player.position.y} - if elements > 10 then - player.surface.create_entity({name = 'fire-flame', position = steps[elements - 1]}) - for i = 1, elements, 1 do - steps[i] = steps[i + 1] - end - steps[elements + 1] = nil - end + if elements > 10 then + player.surface.create_entity({name = "fire-flame", position = steps[elements - 1], }) + for i = 1, elements, 1 do + steps[i] = steps[i+1] + end + steps[elements + 1] = nil + end end function Public_event.shred_simple_entities(entity) - --game.print(entity.name) - if game.forces['enemy'].evolution_factor < 0.25 then - return - end - local simple_entities = - entity.surface.find_entities_filtered( - { - type = {'simple-entity', 'tree'}, - area = {{entity.position.x - 3, entity.position.y - 3}, {entity.position.x + 3, entity.position.y + 3}} - } - ) - if #simple_entities == 0 then - return - end - for i = 1, #simple_entities, 1 do - if not simple_entities[i] then - break - end - if simple_entities[i].valid then - simple_entities[i].die('enemy', simple_entities[i]) - end - end + --game.print(entity.name) + if game.forces["enemy"].evolution_factor < 0.25 then return end + local simple_entities = entity.surface.find_entities_filtered({type = {"simple-entity", "tree"}, area = {{entity.position.x - 3, entity.position.y - 3},{entity.position.x + 3, entity.position.y + 3}}}) + if #simple_entities == 0 then return end + for i = 1, #simple_entities, 1 do + if not simple_entities[i] then break end + if simple_entities[i].valid then + simple_entities[i].die("enemy", simple_entities[i]) + end + end end function Public_event.spawner_loot(surface, position) - local objective = Chrono_table.get_table() - if math_random(1, 20) == 1 then - surface.spill_item_stack( - position, - {name = 'railgun-dart', count = math_random(1, 1 + objective.chronojumps)}, - true - ) - end + local objective = Chrono_table.get_table() + if math_random(1,20) == 1 then + surface.spill_item_stack(position, {name = "railgun-dart", count = math_random(1, 1 + objective.chronojumps)}, true) + end end function Public_event.choppy_loot(event) - local entity = event.entity - local choppy_entity_yield = { - ['tree-01'] = {'iron-ore'}, - ['tree-02-red'] = {'copper-ore'}, - ['tree-04'] = {'coal'}, - ['tree-08-brown'] = {'stone'} - } - if choppy_entity_yield[entity.name] then - if event.buffer then - event.buffer.clear() - end - if not event.player_index then - return - end - local amount = get_ore_amount() - local second_item_amount = math_random(2, 5) - local second_item = 'wood' - local main_item = choppy_entity_yield[entity.name][math_random(1, #choppy_entity_yield[entity.name])] + local entity = event.entity + local choppy_entity_yield = { + ["tree-01"] = {"iron-ore"}, + ["tree-02-red"] = {"copper-ore"}, + ["tree-04"] = {"coal"}, + ["tree-08-brown"] = {"stone"} + } + if choppy_entity_yield[entity.name] then + if event.buffer then event.buffer.clear() end + if not event.player_index then return end + local amount = math_ceil(math_ceil(get_ore_amount() / 5)) + local second_item_amount = math_random(1,3) + local second_item = "wood" + local main_item = choppy_entity_yield[entity.name][math_random(1,#choppy_entity_yield[entity.name])] - entity.surface.create_entity( - { - name = 'flying-text', - position = entity.position, - text = '+' .. - amount .. ' [item=' .. main_item .. '] +' .. second_item_amount .. ' [item=' .. second_item .. ']', - color = {r = 0.8, g = 0.8, b = 0.8} - } - ) + entity.surface.create_entity({ + name = "flying-text", + position = entity.position, + text = "+" .. amount .. " [item=" .. main_item .. "] +" .. second_item_amount .. " [item=" .. second_item .. "]", + color = {r=0.8,g=0.8,b=0.8} + }) - local player = game.players[event.player_index] - reward_ores(amount, main_item, entity.surface, player, player) + local player = game.players[event.player_index] + reward_ores(amount, main_item, entity.surface, player, player) - local inserted_count = player.insert({name = second_item, count = second_item_amount}) - second_item_amount = second_item_amount - inserted_count - if second_item_amount > 0 then - entity.surface.spill_item_stack(entity.position, {name = second_item, count = second_item_amount}, true) - end - end + local inserted_count = player.insert({name = second_item, count = second_item_amount}) + second_item_amount = second_item_amount - inserted_count + if second_item_amount > 0 then + entity.surface.spill_item_stack(entity.position,{name = second_item, count = second_item_amount}, true) + end + end end function Public_event.rocky_loot(event) - local objective = Chrono_table.get_table() - local surface = game.surfaces[objective.active_surface_index] - local player = game.players[event.player_index] - surface.spill_item_stack(player.position, {name = 'raw-fish', count = math_random(1, 3)}, true) - local amount = get_ore_amount() - local rock_mining = { - 'iron-ore', - 'iron-ore', - 'iron-ore', - 'iron-ore', - 'copper-ore', - 'copper-ore', - 'copper-ore', - 'stone', - 'stone', - 'coal', - 'coal' - } - local mined_loot = rock_mining[math_random(1, #rock_mining)] - surface.create_entity( - { - name = 'flying-text', - position = {player.position.x, player.position.y - 0.5}, - text = '+' .. amount .. ' [img=item/' .. mined_loot .. ']', - color = {r = 0.98, g = 0.66, b = 0.22} - } - ) - reward_ores(amount, mined_loot, surface, player, player) + local objective = Chrono_table.get_table() + local surface = game.surfaces[objective.active_surface_index] + local player = game.players[event.player_index] + surface.spill_item_stack(player.position,{name = "raw-fish", count = math_random(1,3)},true) + local amount = math_floor(get_ore_amount()) + local rock_mining = {"iron-ore", "iron-ore", "iron-ore", "iron-ore", "copper-ore", "copper-ore", "copper-ore", "stone", "stone", "coal", "coal"} + local mined_loot = rock_mining[math_random(1,#rock_mining)] + surface.create_entity({ + name = "flying-text", + position = {player.position.x, player.position.y - 0.5}, + text = "+" .. amount .. " [img=item/" .. mined_loot .. "]", + color = {r=0.98, g=0.66, b=0.22} + }) + reward_ores(amount, mined_loot, surface, player, player) end function Public_event.swamp_loot(event) - local objective = Chrono_table.get_table() - local ore_yield = { - ['behemoth-biter'] = 5, - ['behemoth-spitter'] = 5, - ['behemoth-worm-turret'] = 6, - ['big-biter'] = 3, - ['big-spitter'] = 3, - ['big-worm-turret'] = 4, - ['biter-spawner'] = 10, - ['medium-biter'] = 2, - ['medium-spitter'] = 2, - ['medium-worm-turret'] = 3, - ['small-biter'] = 1, - ['small-spitter'] = 1, - ['small-worm-turret'] = 2, - ['spitter-spawner'] = 10 - } - local surface = game.surfaces[objective.active_surface_index] - local amount = get_ore_amount() / 20 - if ore_yield[event.entity.name] then - amount = (get_ore_amount() * ore_yield[event.entity.name]) / 20 - end - if amount > 50 then - amount = 50 - end + local objective = Chrono_table.get_table() + local ore_yield = { + ["behemoth-biter"] = 5, + ["behemoth-spitter"] = 5, + ["behemoth-worm-turret"] = 6, + ["big-biter"] = 3, + ["big-spitter"] = 3, + ["big-worm-turret"] = 4, + ["biter-spawner"] = 10, + ["medium-biter"] = 2, + ["medium-spitter"] = 2, + ["medium-worm-turret"] = 3, + ["small-biter"] = 1, + ["small-spitter"] = 1, + ["small-worm-turret"] = 2, + ["spitter-spawner"] = 10, + } + local surface = game.surfaces[objective.active_surface_index] + local amount = math_floor(get_ore_amount() / 10) + if ore_yield[event.entity.name] then + amount = math_floor((get_ore_amount() * ore_yield[event.entity.name]) / 10) + end + if amount > 50 then amount = 50 end - local rock_mining = {'iron-ore', 'iron-ore', 'coal'} - local mined_loot = rock_mining[math_random(1, #rock_mining)] - --reward_ores(amount, mined_loot, surface, nil, event.entity) - if amount < 5 then - surface.spill_item_stack(event.entity.position, {name = mined_loot, count = amount}, true) - else - surface.create_entity { - name = 'item-on-ground', - position = event.entity.position, - stack = {name = mined_loot, count = amount} - } - end - --surface.spill_item_stack(event.entity.position,{name = mined_loot, count = amount}, true) + local rock_mining = {"iron-ore", "iron-ore", "coal"} + local mined_loot = rock_mining[math_random(1,#rock_mining)] + --reward_ores(amount, mined_loot, surface, nil, event.entity) + if amount < 5 then + surface.spill_item_stack(event.entity.position,{name = mined_loot, count = amount}, true) + else + surface.create_entity{name = "item-on-ground", position = event.entity.position, stack = {name = mined_loot, count = amount}} + end + + event.entity.surface.create_entity({ + name = "flying-text", + position = event.entity.position, + text = "+" .. amount .. " [img=item/" .. mined_loot .. "]", + color = {r=0.7,g=0.8,b=0.4} + }) + + --surface.spill_item_stack(event.entity.position,{name = mined_loot, count = amount}, true) end function Public_event.danger_silo(entity) - local objective = Chrono_table.get_table() - if objective.planet[1].name.id == 19 then - if objective.dangers and #objective.dangers > 1 then - for i = 1, #objective.dangers, 1 do - if entity == objective.dangers[i].silo then - game.print({'chronosphere.message_silo'}, {r = 0.98, g = 0.66, b = 0.22}) - objective.dangers[i].destroyed = true - objective.dangers[i].silo = nil - objective.dangers[i].speaker.destroy() - objective.dangers[i].combinator.destroy() - objective.dangers[i].solar.destroy() - objective.dangers[i].acu.destroy() - objective.dangers[i].pole.destroy() - rendering.destroy(objective.dangers[i].text) - rendering.destroy(objective.dangers[i].timer) - objective.dangers[i].text = -1 - objective.dangers[i].timer = -1 - end - end - end - end + local objective = Chrono_table.get_table() + if objective.planet[1].type.id == 19 then + if objective.dangers and #objective.dangers > 1 then + for i = 1, #objective.dangers, 1 do + if entity == objective.dangers[i].silo then + game.print({"chronosphere.message_silo", Balance.nukes_looted_per_silo(Difficulty.get().difficulty_vote_value)}, {r=0.98, g=0.66, b=0.22}) + objective.dangers[i].destroyed = true + objective.dangers[i].silo = nil + objective.dangers[i].speaker.destroy() + objective.dangers[i].combinator.destroy() + objective.dangers[i].solar.destroy() + objective.dangers[i].acu.destroy() + objective.dangers[i].pole.destroy() + rendering.destroy(objective.dangers[i].text) + rendering.destroy(objective.dangers[i].timer) + objective.dangers[i].text = -1 + objective.dangers[i].timer = -1 + end + end + end + end end function Public_event.biter_immunities(event) - --local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - local planet = objective.planet[1].name.id - if event.damage_type.name == 'fire' then - if planet == 14 then --lava planet - event.entity.health = event.entity.health + event.final_damage_amount - local fire = event.entity.stickers - if fire and #fire > 0 then - for i = 1, #fire, 1 do - if fire[i].sticked_to == event.entity and fire[i].name == 'fire-sticker' then - fire[i].destroy() - break - end - end - end - -- else -- other planets - -- event.entity.health = math_floor(event.entity.health + event.final_damage_amount - (event.final_damage_amount / (1 + 0.02 * Diff.difficulty_vote_value * objective.chronojumps))) - end - elseif event.damage_type.name == 'poison' then - if planet == 18 then --swamp planet - event.entity.health = event.entity.health + event.final_damage_amount - end - end + local objective = Chrono_table.get_table() + local planet = objective.planet[1].type.id + if event.damage_type.name == "fire" then + if planet == 14 then --lava planet + event.entity.health = event.entity.health + event.final_damage_amount + local fire = event.entity.stickers + if fire and #fire > 0 then + for i = 1, #fire, 1 do + if fire[i].sticked_to == event.entity and fire[i].name == "fire-sticker" then fire[i].destroy() break end + end + end + -- else -- other planets + -- event.entity.health = math_floor(event.entity.health + event.final_damage_amount - (event.final_damage_amount / (1 + 0.02 * Difficulty.get().difficulty_vote_value * objective.chronojumps))) + end + elseif event.damage_type.name == "poison" then + if planet == 18 then --swamp planet + event.entity.health = event.entity.health + event.final_damage_amount + end + end end function Public_event.flamer_nerfs() - local objective = Chrono_table.get_table() - local Diff = Difficulty.get() - local flamer_power = 0 - local difficulty = Diff.difficulty_vote_value - if difficulty > 1 then - difficulty = 1 + ((difficulty - 1) / 2) - elseif difficulty < 1 then - difficulty = 1 - ((1 - difficulty) / 2) - end - local flame_researches = { - [1] = {name = 'refined-flammables-1', bonus = 0.2}, - [2] = {name = 'refined-flammables-2', bonus = 0.2}, - [3] = {name = 'refined-flammables-3', bonus = 0.2}, - [4] = {name = 'refined-flammables-4', bonus = 0.3}, - [5] = {name = 'refined-flammables-5', bonus = 0.3}, - [6] = {name = 'refined-flammables-6', bonus = 0.4}, - [7] = {name = 'refined-flammables-7', bonus = 0.2} - } - for i = 1, 6, 1 do - if game.forces.player.technologies[flame_researches[i].name].researched then - flamer_power = flamer_power + flame_researches[i].bonus - end - end - flamer_power = flamer_power + (game.forces.player.technologies[flame_researches[7].name].level - 7) * 0.2 - game.forces.player.set_ammo_damage_modifier( - 'flamethrower', - flamer_power - 0.02 * difficulty * objective.chronojumps - ) - game.forces.player.set_turret_attack_modifier( - 'flamethrower-turret', - flamer_power - 0.02 * difficulty * objective.chronojumps - ) + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + local flame_researches = { + [1] = {name = "refined-flammables-1", bonus = 0.2}, + [2] = {name = "refined-flammables-2", bonus = 0.2}, + [3] = {name = "refined-flammables-3", bonus = 0.2}, + [4] = {name = "refined-flammables-4", bonus = 0.3}, + [5] = {name = "refined-flammables-5", bonus = 0.3}, + [6] = {name = "refined-flammables-6", bonus = 0.4}, + [7] = {name = "refined-flammables-7", bonus = 0.2} + } + + local flamer_power = 0 + for i = 1, 6, 1 do + if game.forces.player.technologies[flame_researches[i].name].researched then + flamer_power = flamer_power + flame_researches[i].bonus + end + end + flamer_power = flamer_power + (game.forces.player.technologies[flame_researches[7].name].level - 7) * 0.2 + + game.forces.player.set_ammo_damage_modifier("flamethrower", flamer_power - Balance.flamers_nerfs_size(objective.chronojumps, difficulty)) + game.forces.player.set_turret_attack_modifier("flamethrower-turret", flamer_power - Balance.flamers_nerfs_size(objective.chronojumps, difficulty)) end local mining_researches = { - -- these already give .1 productivity so we're only adding .1 to get to 20% - ['mining-productivity-1'] = {bonus_productivity = .1, bonus_mining_speed = .2, bonus_inventory = 10}, - ['mining-productivity-2'] = {bonus_productivity = .1, bonus_mining_speed = .2, bonus_inventory = 10}, - ['mining-productivity-3'] = {bonus_productivity = .1, bonus_mining_speed = .2, bonus_inventory = 10}, - ['mining-productivity-4'] = { - bonus_productivity = .1, - bonus_mining_speed = .2, - bonus_inventory = 10, - infinite = true, - infinite_level = 4 - } + -- these already give .1 productivity so we're only adding .1 to get to 20% + ["mining-productivity-1"] = {bonus_productivity = .1, bonus_mining_speed = .2, bonus_inventory = 10}, + ["mining-productivity-2"] = {bonus_productivity = .1, bonus_mining_speed = .2, bonus_inventory = 10}, + ["mining-productivity-3"] = {bonus_productivity = .1, bonus_mining_speed = .2, bonus_inventory = 10}, + ["mining-productivity-4"] = {bonus_productivity = .1, bonus_mining_speed = .2, bonus_inventory = 10, infinite = true, infinite_level = 4}, } function Public_event.mining_buffs(event) - if event == nil then - -- initialization/reset call - game.forces.player.mining_drill_productivity_bonus = game.forces.player.mining_drill_productivity_bonus + 1 - game.forces.player.manual_mining_speed_modifier = game.forces.player.manual_mining_speed_modifier + 1 - return - end - if mining_researches[event.research.name] == nil then - return - end - local tech = mining_researches[event.research.name] + if event == nil then + -- initialization/reset call + game.forces.player.mining_drill_productivity_bonus = game.forces.player.mining_drill_productivity_bonus + 1 + game.forces.player.manual_mining_speed_modifier = game.forces.player.manual_mining_speed_modifier + 1 + return + end - if tech.bonus_productivity then - game.forces.player.mining_drill_productivity_bonus = - game.forces.player.mining_drill_productivity_bonus + tech.bonus_productivity - end + if mining_researches[event.research.name] == nil then return end + + local tech = mining_researches[event.research.name] - if tech.bonus_mining_speed then - game.forces.player.manual_mining_speed_modifier = - game.forces.player.manual_mining_speed_modifier + tech.bonus_mining_speed - end + if tech.bonus_productivity then + game.forces.player.mining_drill_productivity_bonus = game.forces.player.mining_drill_productivity_bonus + tech.bonus_productivity + end - if tech.bonus_inventory then - game.forces.player.character_inventory_slots_bonus = - game.forces.player.character_inventory_slots_bonus + tech.bonus_inventory - end + if tech.bonus_mining_speed then + game.forces.player.manual_mining_speed_modifier = game.forces.player.manual_mining_speed_modifier + tech.bonus_mining_speed + end + + if tech.bonus_inventory then + game.forces.player.character_inventory_slots_bonus = game.forces.player.character_inventory_slots_bonus + tech.bonus_inventory + end end function Public_event.on_technology_effects_reset(event) - local objective = Chrono_table.get_table() - if event.force.name == 'player' then - game.forces.player.character_inventory_slots_bonus = - game.forces.player.character_inventory_slots_bonus + objective.invupgradetier * 10 - game.forces.player.character_loot_pickup_distance_bonus = - game.forces.player.character_loot_pickup_distance_bonus + objective.pickupupgradetier + local objective = Chrono_table.get_table() + if event.force.name == "player" then + game.forces.player.character_inventory_slots_bonus = game.forces.player.character_inventory_slots_bonus + objective.invupgradetier * 10 + game.forces.player.character_loot_pickup_distance_bonus = game.forces.player.character_loot_pickup_distance_bonus + objective.pickupupgradetier - local fake_event = {} - Public_event.mining_buffs(nil) - for tech, bonuses in pairs(mining_researches) do - tech = game.forces.player.technologies[tech] - if tech.researched == true or bonuses.infinite == true then - fake_event.research = tech - if bonuses.infinite and bonuses.infinite_level and tech.level > bonuses.infinite_level then - for i = bonuses.infinite_level, tech.level - 1 do - Public_event.mining_buffs(fake_event) - end - else - Public_event.mining_buffs(fake_event) - end - end - end - end + local fake_event = {} + Public_event.mining_buffs(nil) + for tech, bonuses in pairs(mining_researches) do + tech = game.forces.player.technologies[tech] + if tech.researched == true or bonuses.infinite == true then + fake_event.research = tech + if bonuses.infinite and bonuses.infinite_level and tech.level > bonuses.infinite_level then + for i = bonuses.infinite_level, tech.level - 1 do + Public_event.mining_buffs(fake_event) + end + else + Public_event.mining_buffs(fake_event) + end + end + end + end end return Public_event diff --git a/maps/chronosphere/gui.lua b/maps/chronosphere/gui.lua index 14bade68..abf160f1 100644 --- a/maps/chronosphere/gui.lua +++ b/maps/chronosphere/gui.lua @@ -6,6 +6,8 @@ local math_abs = math.abs local math_max = math.max local math_min = math.min local Upgrades = require "maps.chronosphere.upgrade_list" +local Balance = require "maps.chronosphere.balance" +local Difficulty = require 'modules.difficulty_vote' local function create_gui(player) local frame = player.gui.top.add({ type = "frame", name = "chronosphere"}) @@ -109,8 +111,53 @@ local function update_upgrades_gui(player) end end + + +local function planet_gui(player) + local objective = Chrono_table.get_table() + if player.gui.screen["gui_planet"] then player.gui.screen["gui_planet"].destroy() return end + local planet = objective.planet[1] + local evolution = game.forces["enemy"].evolution_factor + local frame = player.gui.screen.add{type = "frame", name = "gui_planet", caption = "Planet Info", direction = "vertical"} + frame.location = {x = 650, y = 45} + frame.style.minimal_height = 300 + frame.style.maximal_height = 500 + frame.style.minimal_width = 200 + frame.style.maximal_width = 400 + local l = {} + l[1] = frame.add({type = "label", name = "planet_name", caption = {"chronosphere.gui_planet_0", planet.type.name}}) + l[2] = frame.add({type = "label", caption = {"chronosphere.gui_planet_1"}}) + local table0 = frame.add({type = "table", name = "planet_ores", column_count = 3}) + table0.add({type = "sprite-button", name = "iron-ore", sprite = "item/iron-ore", enabled = false, number = planet.type.iron}) + table0.add({type = "sprite-button", name = "copper-ore", sprite = "item/copper-ore", enabled = false, number = planet.type.copper}) + table0.add({type = "sprite-button", name = "coal", sprite = "item/coal", enabled = false, number = planet.type.coal}) + table0.add({type = "sprite-button", name = "stone", sprite = "item/stone", enabled = false, number = planet.type.stone}) + table0.add({type = "sprite-button", name = "uranium-ore", sprite = "item/uranium-ore", enabled = false, number = planet.type.uranium}) + table0.add({type = "sprite-button", name = "oil", sprite = "fluid/crude-oil", enabled = false, number = planet.type.oil}) + l[3] = frame.add({type = "label", name = "richness", caption = {"chronosphere.gui_planet_2", planet.ore_richness.name}}) + frame.add({type = "label", name = "planet_time", caption = {"chronosphere.gui_planet_5", planet.day_speed.name}}) + frame.add({type = "line"}) + frame.add({type = "label", name = "planet_biters", caption = {"chronosphere.gui_planet_3", math_floor(evolution * 1000) / 10}}) + frame.add({type = "label", name = "planet_biters2", caption = {"chronosphere.gui_planet_4"}}) + frame.add({type = "label", name = "planet_biters3", caption = {"chronosphere.gui_planet_4_1", objective.overstaycount * 2.5, objective.overstaycount * 10}}) + frame.add({type = "line"}) + frame.add({type = "label", name = "overstay_time", caption = {"chronosphere.gui_planet_7", "",""}}) + + frame.add({type = "line"}) + + local close = frame.add({type = "button", name = "close_planet", caption = "Close"}) + close.style.horizontal_align = "center" + -- for i = 1, 3, 1 do + -- l[i].style.font = "default-game" + -- end + + return l +end + local function update_planet_gui(player) local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + if not player.gui.screen["gui_planet"] then return end local planet = objective.planet[1] local evolution = game.forces["enemy"].evolution_factor @@ -121,24 +168,62 @@ local function update_planet_gui(player) } local frame = player.gui.screen["gui_planet"] - frame["planet_name"].caption = {"chronosphere.gui_planet_0", planet.name.name} - frame["planet_ores"]["iron-ore"].number = planet.name.iron - frame["planet_ores"]["copper-ore"].number = planet.name.copper - frame["planet_ores"]["coal"].number = planet.name.coal - frame["planet_ores"]["stone"].number = planet.name.stone - frame["planet_ores"]["uranium-ore"].number = planet.name.uranium - frame["planet_ores"]["oil"].number = planet.name.oil + frame["planet_name"].caption = {"chronosphere.gui_planet_0", planet.type.name} + frame["planet_ores"]["iron-ore"].number = planet.type.iron + frame["planet_ores"]["copper-ore"].number = planet.type.copper + frame["planet_ores"]["coal"].number = planet.type.coal + frame["planet_ores"]["stone"].number = planet.type.stone + frame["planet_ores"]["uranium-ore"].number = planet.type.uranium + frame["planet_ores"]["oil"].number = planet.type.oil frame["richness"].caption = {"chronosphere.gui_planet_2", planet.ore_richness.name} frame["planet_biters"].caption = {"chronosphere.gui_planet_3", math_floor(evolution * 1000) / 10} frame["planet_biters"].style.font_color = evo_color - frame["planet_biters3"].caption = {"chronosphere.gui_planet_4_1", objective.passivejumps * 2.5, objective.passivejumps * 10} + frame["planet_biters3"].caption = {"chronosphere.gui_planet_4_1", objective.overstaycount * 2.5, objective.overstaycount * 10} frame["planet_time"].caption = {"chronosphere.gui_planet_5", planet.day_speed.name} + + if objective.jump_countdown_start_time == -1 then + if objective.chronojumps >= Balance.jumps_until_overstay_is_on(difficulty) then + local time_until_overstay = (objective.chronochargesneeded * 0.75 / objective.passive_chronocharge_rate - objective.passivetimer) + if time_until_overstay < 0 then + frame["overstay_time"].caption = {"chronosphere.gui_overstayed","",""} + else + frame["overstay_time"].caption = {"chronosphere.gui_planet_6", math_floor(time_until_overstay / 60), math_floor(time_until_overstay % 60)} + end + else + frame["overstay_time"].caption = {"chronosphere.gui_planet_7",Balance.jumps_until_overstay_is_on(difficulty),""} + end + else + if objective.chronojumps >= Balance.jumps_until_overstay_is_on(difficulty) then + local overstayed = (objective.chronochargesneeded * 0.75 / objective.passive_chronocharge_rate < objective.jump_countdown_start_time) + if overstayed < 0 then + frame["overstay_time"].caption = {"chronosphere.gui_overstayed","",""} + else + frame["overstay_time"].caption = {"chronosphere.gui_not_overstayed","",""} + end + end + end end +local function ETA_seconds_until_full(power, storedbattery) -- in watts and joules + local objective = Chrono_table.get_table() + + local n = objective.chronochargesneeded - objective.chronocharges + + if n <= 0 then return 0 + else + local eta = math_max(0, n - storedbattery/1000000) / (power/1000000 + objective.passive_chronocharge_rate) + if eta < 1 then return 1 end + return math_floor(eta) + end +end + function Public_gui.update_gui(player) local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + local tick = game.tick update_planet_gui(player) update_upgrades_gui(player) if not player.gui.top.chronosphere then create_gui(player) end @@ -147,48 +232,91 @@ function Public_gui.update_gui(player) gui.label.caption = {"chronosphere.gui_1"} gui.jump_number.caption = objective.chronojumps - local interval = objective.chrononeeds - gui.progressbar.value = 1 - (objective.chrononeeds - objective.chronotimer) / interval + local interval = objective.chronochargesneeded + gui.progressbar.value = 1 - (objective.chronochargesneeded - objective.chronocharges) / interval gui.charger.caption = {"chronosphere.gui_2"} - gui.charger_value.caption = objective.chronotimer .. " / " .. objective.chrononeeds - gui.timer.caption = {"chronosphere.gui_3"} - gui.timer_value.caption = math_floor((objective.chrononeeds - objective.chronotimer) / 60) .. " min, " .. (objective.chrononeeds - objective.chronotimer) % 60 .. " s" - if objective.chronojumps > 5 then - local overstay_timer_min = math_floor((objective.chrononeeds * 0.75 - objective.passivetimer) / 60) - local evo_timer_min = math_floor((objective.chrononeeds * 0.5 - objective.passivetimer) / 60) - local first_part = "If overstaying this, other planets can evolve: " .. overstay_timer_min .. " min, " .. (objective.chrononeeds * 0.75 - objective.passivetimer) % 60 .. " s" - if overstay_timer_min < 0 then - first_part = "If overstaying this, other planets can evolve: " .. overstay_timer_min .. " min, " .. 59 - ((objective.chrononeeds * 0.75 - objective.passivetimer) % 60) .. " s" - end - local second_part = "This planet gets additional evolution growth in: " ..evo_timer_min .. " min, " .. (objective.chrononeeds * 0.5 - objective.passivetimer) % 60 .. " s" - if evo_timer_min < 0 then - second_part = "This planet gets additional evolution growth in: " ..evo_timer_min .. " min, " .. 59 -((objective.chrononeeds * 0.5 - objective.passivetimer) % 60) .. " s" - end - gui.timer_value.tooltip = first_part .. "\n" .. second_part + --[[ + if (objective.chronochargesneeded<1000) then + gui.charger_value.caption = objective.chronocharges .. "/" .. objective.chronochargesneeded .. " MJ" + elseif (objective.chronochargesneeded<10000) then + gui.charger_value.caption = math_floor(objective.chronocharges/10)/100 .. " / " .. math_floor(objective.chronochargesneeded/10)/100 .. " GJ" + elseif (objective.chronochargesneeded<1000000) then + gui.charger_value.caption = math_floor(objective.chronocharges/100)/10 .. " / " .. math_floor(objective.chronochargesneeded/100)/10 .. " GJ" + elseif (objective.chronochargesneeded<10000000) then + gui.charger_value.caption = math_floor(objective.chronocharges/10000)/100 .. " / " .. math_floor(objective.chronochargesneeded/10000)/100 .. " TJ" else - gui.timer_value.tooltip = "After planet 5, biters will get additional permanent evolution for staying too long on each planet." + gui.charger_value.caption = math_floor(objective.chronocharges/100000)/10 .. " / " .. math_floor(objective.chronochargesneeded/100000)/10 .. " TJ" + end + ]] + + if (objective.chronochargesneeded<100000) then + gui.charger_value.caption = string.format("%.2f", objective.chronocharges/1000) .. " / " .. math_floor(objective.chronochargesneeded)/1000 .. " GJ" + else + gui.charger_value.caption = string.format("%.2f", objective.chronocharges/1000000) .. " / " .. math_floor(objective.chronochargesneeded)/1000000 .. " TJ" + end + + if objective.jump_countdown_start_time == -1 then + if tick % 60 == 58 then -- charge history updates + local history = objective.accumulator_energy_history + objective.accumulator_energy_history = {} + local powerobserved,storedbattery,seconds_ETA = 0,0,0 + if #history == 2 and history[1] and history[2] then + powerobserved = (history[2] - history[1]) / 54 * 60 + storedbattery = history[2] + end + + seconds_ETA = ETA_seconds_until_full(powerobserved, storedbattery) + + gui.timer.caption = {"chronosphere.gui_3"} + gui.timer_value.caption = math_floor(seconds_ETA / 60) .. "m" .. seconds_ETA % 60 .. "s" + + if objective.planet[1].type.id == 19 and objective.passivetimer > 31 then + local nukecase = objective.dangertimer + gui.timer2.caption = {"chronosphere.gui_3_2"} + gui.timer_value2.caption = math_floor(nukecase / 60) .. "m" .. nukecase % 60 .. "s" + gui.timer2.style.font_color = {r=0.98, g=0, b=0} + gui.timer_value2.style.font_color = {r=0.98, g=0, b=0} + else + local bestcase = 0 + if objective.accumulators then bestcase = math_floor(ETA_seconds_until_full(#objective.accumulators * 300000, storedbattery)) + gui.timer2.caption = {"chronosphere.gui_3_1"} + gui.timer_value2.caption = math_floor(bestcase / 60) .. "m" .. bestcase % 60 .. "s (drawing " .. #objective.accumulators * 0.3 .. "MW)" + gui.timer2.style.font_color = {r = 0, g = 200, b = 0} + gui.timer_value2.style.font_color = {r = 0, g = 200, b = 0} + end + end + end + if objective.chronojumps >= Balance.jumps_until_overstay_is_on(difficulty) then + local time_until_overstay = (objective.chronochargesneeded * 0.75 / objective.passive_chronocharge_rate - objective.passivetimer) + local time_until_evo = (objective.chronochargesneeded * 0.5 / objective.passive_chronocharge_rate - objective.passivetimer) + + local first_part = "Biters permanently evolve in: " .. math_floor(time_until_overstay/60) .. "m" .. math_floor(time_until_overstay) % 60 .. "s" + if time_until_overstay < 0 then + first_part = "Biters permanently evolve in: " .. math_floor(time_until_overstay/60) .. "m" .. 59 - (math_floor(time_until_overstay) % 60) .. "s" + end + + local second_part = "Evolution ramps up on this planet in: " .. math_floor(time_until_evo/60) .. "m" .. math_floor(time_until_evo) % 60 .. "s" + if time_until_evo < 0 then + second_part = "Evolution ramps up on this planet in: " .. math_floor(time_until_evo/60) .. "m" .. 59 - (math_floor(time_until_evo) % 60) .. "s" + end + + gui.timer_value.tooltip = first_part .. "\n" .. second_part + else + gui.timer_value.tooltip = "" + end + else + gui.timer.caption = {"chronosphere.gui_3_3"} + gui.timer_value.caption = objective.passivetimer - objective.jump_countdown_start_time .. " / " .. objective.jump_countdown_length + gui.timer.tooltip = "" + gui.timer_value.tooltip = "" + gui.timer2.caption = "" + gui.timer_value2.caption = "" end gui.planet_button.caption = {"chronosphere.gui_planet_button"} gui.upgrades_button.caption = {"chronosphere.gui_upgrades_button"} - - local acus = 0 - if objective.acumulators then acus = #objective.acumulators end - local bestcase = math_floor((objective.chrononeeds - objective.chronotimer) / (1 + math_floor(acus/10))) - local nukecase = objective.dangertimer - if objective.planet[1].name.id == 19 and objective.passivetimer > 31 then - gui.timer2.caption = {"chronosphere.gui_3_2"} - gui.timer_value2.caption = math_floor(nukecase / 60) .. " min, " .. nukecase % 60 .. " s" - gui.timer2.style.font_color = {r=0.98, g=0, b=0} - gui.timer_value2.style.font_color = {r=0.98, g=0, b=0} - else - gui.timer2.caption = {"chronosphere.gui_3_1"} - gui.timer_value2.caption = math_floor(bestcase / 60) .. " min, " .. bestcase % 60 .. " s (when using " .. acus * 0.3 .. "MW)" - gui.timer2.style.font_color = {r = 0, g = 200, b = 0} - gui.timer_value2.style.font_color = {r = 0, g = 200, b = 0} - end end local function upgrades_gui(player) @@ -235,43 +363,6 @@ local function upgrades_gui(player) return costs end -local function planet_gui(player) - local objective = Chrono_table.get_table() - if player.gui.screen["gui_planet"] then player.gui.screen["gui_planet"].destroy() return end - local planet = objective.planet[1] - local evolution = game.forces["enemy"].evolution_factor - local frame = player.gui.screen.add{type = "frame", name = "gui_planet", caption = "Planet Info", direction = "vertical"} - frame.location = {x = 650, y = 45} - frame.style.minimal_height = 300 - frame.style.maximal_height = 500 - frame.style.minimal_width = 200 - frame.style.maximal_width = 400 - local l = {} - l[1] = frame.add({type = "label", name = "planet_name", caption = {"chronosphere.gui_planet_0", planet.name.name}}) - l[2] = frame.add({type = "label", caption = {"chronosphere.gui_planet_1"}}) - local table0 = frame.add({type = "table", name = "planet_ores", column_count = 3}) - table0.add({type = "sprite-button", name = "iron-ore", sprite = "item/iron-ore", enabled = false, number = planet.name.iron}) - table0.add({type = "sprite-button", name = "copper-ore", sprite = "item/copper-ore", enabled = false, number = planet.name.copper}) - table0.add({type = "sprite-button", name = "coal", sprite = "item/coal", enabled = false, number = planet.name.coal}) - table0.add({type = "sprite-button", name = "stone", sprite = "item/stone", enabled = false, number = planet.name.stone}) - table0.add({type = "sprite-button", name = "uranium-ore", sprite = "item/uranium-ore", enabled = false, number = planet.name.uranium}) - table0.add({type = "sprite-button", name = "oil", sprite = "fluid/crude-oil", enabled = false, number = planet.name.oil}) - l[3] = frame.add({type = "label", name = "richness", caption = {"chronosphere.gui_planet_2", planet.ore_richness.name}}) - frame.add({type = "line"}) - frame.add({type = "label", name = "planet_biters", caption = {"chronosphere.gui_planet_3", math_floor(evolution * 1000) / 10}}) - frame.add({type = "label", name = "planet_biters2", caption = {"chronosphere.gui_planet_4"}}) - frame.add({type = "label", name = "planet_biters3", caption = {"chronosphere.gui_planet_4_1", objective.passivejumps * 2.5, objective.passivejumps * 10}}) - frame.add({type = "line"}) - frame.add({type = "label", name = "planet_time", caption = {"chronosphere.gui_planet_5", planet.day_speed.name}}) - frame.add({type = "line"}) - local close = frame.add({type = "button", name = "close_planet", caption = "Close"}) - close.style.horizontal_align = "center" - -- for i = 1, 3, 1 do - -- l[i].style.font = "default-game" - -- end - return l -end - function Public_gui.on_gui_click(event) if not event then return end if not event.element then return end diff --git a/maps/chronosphere/locomotive.lua b/maps/chronosphere/locomotive.lua index 3ef2cf25..db10fb9a 100644 --- a/maps/chronosphere/locomotive.lua +++ b/maps/chronosphere/locomotive.lua @@ -1,4 +1,5 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' local Public = {} local Upgrades = require "maps.chronosphere.upgrade_list" local math_floor = math.floor @@ -11,7 +12,7 @@ function Public.locomotive_spawn(surface, position, wagons) surface.request_to_generate_chunks(position, 0.5) surface.force_generate_chunk_requests() local objective = Chrono_table.get_table() - if objective.planet[1].name.id == 17 then --fish market + if objective.planet[1].type.id == 17 then --fish market position.x = position.x - 960 position.y = position.y - 64 end @@ -38,7 +39,7 @@ function Public.locomotive_spawn(surface, position, wagons) objective.locomotive.minable = false --if not objective.comfychests then objective.comfychests = {} end - --if not objective.acumulators then objective.acumulators = {} end + --if not objective.accumulators then objective.accumulators = {} end for i = 1, 24, 1 do local yi = 0 local xi = 5 @@ -108,29 +109,12 @@ function Public.fish_tag() }) end -local market_offers = { - {price = {{'coin', 10}}, offer = {type = 'give-item', item = "raw-fish"}}, - {price = {{"coin", 20}}, offer = {type = 'give-item', item = 'wood', count = 50}}, - {price = {{"coin", 50}}, offer = {type = 'give-item', item = 'iron-ore', count = 50}}, - {price = {{"coin", 50}}, offer = {type = 'give-item', item = 'copper-ore', count = 50}}, - {price = {{"coin", 50}}, offer = {type = 'give-item', item = 'stone', count = 50}}, - {price = {{"coin", 50}}, offer = {type = 'give-item', item = 'coal', count = 50}}, - {price = {{"coin", 200}}, offer = {type = 'give-item', item = 'uranium-ore', count = 50}}, - {price = {{"coin", 25}, {"empty-barrel", 1}}, offer = {type = 'give-item', item = 'crude-oil-barrel', count = 1}}, - {price = {{"coin", 200}, {"steel-plate", 20}, {"electronic-circuit", 20}}, offer = {type = 'give-item', item = 'loader', count = 1}}, - {price = {{"coin", 400}, {"steel-plate", 40}, {"advanced-circuit", 10}, {"loader", 1}}, offer = {type = 'give-item', item = 'fast-loader', count = 1}}, - {price = {{"coin", 600}, {"express-transport-belt", 10}, {"fast-loader", 1}}, offer = {type = 'give-item', item = 'express-loader', count = 1}}, - --{price = {{"coin", 5}, {"stone", 100}}, offer = {type = 'give-item', item = 'landfill', count = 1}}, - {price = {{"coin", 1}, {"steel-plate", 1}, {"explosives", 10}}, offer = {type = 'give-item', item = 'land-mine', count = 1}}, - {price = {{"pistol", 1}}, offer = {type = "give-item", item = "iron-plate", count = 100}} -} - function Public.create_wagon_room() local objective = Chrono_table.get_table() local width = 64 local height = 384 objective.comfychests2 = {} - objective.acumulators = {} + objective.accumulators = {} local map_gen_settings = { ["width"] = width, ["height"] = height + 128, @@ -210,7 +194,7 @@ function Public.create_wagon_room() for y = height * -0.5 + 7, height * -0.5 + 10, 1 do local p = {x,y} surface.set_tiles({{name = "water", position = p}}) - if math_random(1, 3) == 1 then surface.create_entity({name = "fish", position = p}) end + if math_random(1, 3) == 1 and (x ~= width * -0.4 + 6) and (y ~= height * -0.5 + 7) then surface.create_entity({name = "fish", position = p}) end end end @@ -299,14 +283,14 @@ function Public.create_wagon_room() end acumulator.minable = false acumulator.destructible = false - table.insert(objective.acumulators, acumulator) + table.insert(objective.accumulators, acumulator) end for k = 1, 4, 1 do local xx = x + 2 * k local acumulator = surface.create_entity({name = "accumulator", position = {xx,y}, force="player", create_build_effect_smoke = false}) acumulator.minable = false acumulator.destructible = false - table.insert(objective.acumulators, acumulator) + table.insert(objective.accumulators, acumulator) end end @@ -323,7 +307,7 @@ function Public.create_wagon_room() repairchest.destructible = false objective.upgradechest[0] = repairchest rendering.draw_text{ - text = "Repair chest", + text = "Repair Chest", surface = surface, target = repairchest, target_offset = {0, -2.5}, @@ -350,7 +334,7 @@ function Public.create_wagon_room() end local market1_text = rendering.draw_text{ - text = "Resources", + text = "Market", surface = surface, target = market, target_offset = {0, -3.5}, @@ -372,7 +356,7 @@ function Public.create_wagon_room() scale_with_zoom = false } local upgrade_sub_text = rendering.draw_text{ - text = "Click [Upgrades] on top of screen", + text = "Click [Upgrades] at top of screen", surface = surface, target = objective.upgradechest[8], target_offset = {0, -2.5}, @@ -384,7 +368,7 @@ function Public.create_wagon_room() } - for _, offer in pairs(market_offers) do market.add_market_item(offer) end + for _, offer in pairs(Balance.market_offers()) do market.add_market_item(offer) end --generate cars-- local car_pos = { @@ -416,41 +400,7 @@ function Public.create_wagon_room() end table.shuffle_table(positions) - local cargo_boxes = { - {name = "grenade", count = math_random(2, 5)}, - {name = "grenade", count = math_random(2, 5)}, - {name = "grenade", count = math_random(2, 5)}, - {name = "submachine-gun", count = 1}, - {name = "submachine-gun", count = 1}, - {name = "submachine-gun", count = 1}, - {name = "land-mine", count = math_random(8, 12)}, - {name = "iron-gear-wheel", count = math_random(7, 15)}, - {name = "iron-gear-wheel", count = math_random(7, 15)}, - {name = "iron-gear-wheel", count = math_random(7, 15)}, - {name = "iron-gear-wheel", count = math_random(7, 15)}, - {name = "iron-plate", count = math_random(15, 23)}, - {name = "iron-plate", count = math_random(15, 23)}, - {name = "iron-plate", count = math_random(15, 23)}, - {name = "iron-plate", count = math_random(15, 23)}, - {name = "iron-plate", count = math_random(15, 23)}, - {name = "copper-plate", count = math_random(15, 23)}, - {name = "copper-plate", count = math_random(15, 23)}, - {name = "copper-plate", count = math_random(15, 23)}, - {name = "copper-plate", count = math_random(15, 23)}, - {name = "copper-plate", count = math_random(15, 23)}, - {name = "shotgun", count = 1}, - {name = "shotgun", count = 1}, - {name = "shotgun", count = 1}, - {name = "shotgun-shell", count = math_random(5, 7)}, - {name = "shotgun-shell", count = math_random(5, 7)}, - {name = "shotgun-shell", count = math_random(5, 7)}, - {name = "firearm-magazine", count = math_random(7, 15)}, - {name = "firearm-magazine", count = math_random(7, 15)}, - {name = "firearm-magazine", count = math_random(7, 15)}, - {name = "rail", count = math_random(16, 24)}, - {name = "rail", count = math_random(16, 24)}, - {name = "rail", count = math_random(16, 24)}, - } + local cargo_boxes = Balance.initial_cargo_boxes() local i = 1 for _ = 1, 16, 1 do @@ -468,7 +418,10 @@ function Public.create_wagon_room() end for loot_i = 1, #cargo_boxes, 1 do - if not positions[i] then break end + if not positions[i] then + log("ran out of cargo box positions") + break + end local e = surface.create_entity({name = "wooden-chest", position = positions[i], force="player", create_build_effect_smoke = false}) local inventory = e.get_inventory(defines.inventory.chest) inventory.insert(cargo_boxes[loot_i]) @@ -481,12 +434,21 @@ function Public.set_player_spawn_and_refill_fish() if not objective.locomotive_cargo[1] then return end local cargo = objective.locomotive_cargo[1] if not cargo.valid then return end - cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = "raw-fish", count = math_random(1, 2)}) + cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = "raw-fish", count = 1}) local position = cargo.surface.find_non_colliding_position("stone-furnace", cargo.position, 16, 2) if not position then return end game.forces.player.set_spawn_position({x = position.x, y = position.y}, cargo.surface) end +function Public.award_coins(_count) + if not (_count >= 1) then return end + local objective = Chrono_table.get_table() + if not objective.locomotive_cargo[1] then return end + local cargo = objective.locomotive_cargo[1] + if not cargo.valid then return end + cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = "coin", count = math_floor(_count)}) +end + function Public.enter_cargo_wagon(player, vehicle) local objective = Chrono_table.get_table() if not vehicle then log("no vehicle") return end diff --git a/maps/chronosphere/main.lua b/maps/chronosphere/main.lua index dd0bbba6..1e2487d2 100644 --- a/maps/chronosphere/main.lua +++ b/maps/chronosphere/main.lua @@ -1,426 +1,539 @@ -- chronosphere -- -require 'modules.difficulty_vote' -require 'modules.biters_yield_coins' -require 'modules.no_deconstruction_of_neutral_entities' +require "modules.difficulty_vote" +require "modules.biters_yield_coins" +require "modules.no_deconstruction_of_neutral_entities" --require "modules.no_solar" -require 'modules.shotgun_buff' -require 'modules.mineable_wreckage_yields_scrap' -require 'maps.chronosphere.comfylatron' -require 'maps.chronosphere.terrain' -require 'on_tick_schedule' -require 'modules.biter_noms_you' +require "maps.chronosphere.comfylatron" +require "maps.chronosphere.terrain" +require "on_tick_schedule" +require "modules.biter_noms_you" +-- require "modules.custom_death_messages" local Server = require 'utils.server' -local Ai = require 'maps.chronosphere.ai' -local Planets = require 'maps.chronosphere.chronobubles' -local Ores = require 'maps.chronosphere.ores' -local Reset = require 'functions.soft_reset' -local Map = require 'modules.map_info' -local Upgrades = require 'maps.chronosphere.upgrades' -local Tick_functions = require 'maps.chronosphere.tick_functions' -local Event_functions = require 'maps.chronosphere.event_functions' -local Chrono = require 'maps.chronosphere.chrono' +local Ai = require "maps.chronosphere.ai" +local Planets = require "maps.chronosphere.chronobubles" +local Ores =require "maps.chronosphere.ores" +local Reset = require "functions.soft_reset" +local Map = require "modules.map_info" +local Upgrades = require "maps.chronosphere.upgrades" +local Tick_functions = require "maps.chronosphere.tick_functions" +local Event_functions = require "maps.chronosphere.event_functions" +local Balance = require "maps.chronosphere.balance" +local Rand = require 'maps.chronosphere.random' +local Chrono = require "maps.chronosphere.chrono" local Chrono_table = require 'maps.chronosphere.table' -local Locomotive = require 'maps.chronosphere.locomotive' -local Gui = require 'maps.chronosphere.gui' +local Locomotive = require "maps.chronosphere.locomotive" +local Gui = require "maps.chronosphere.gui" local Difficulty = require 'modules.difficulty_vote' local math_random = math.random local math_floor = math.floor local math_sqrt = math.sqrt -require 'maps.chronosphere.config_tab' +require "maps.chronosphere.config_tab" local Public = {} -local starting_items = { - ['pistol'] = 1, - ['firearm-magazine'] = 32, - ['grenade'] = 4, - ['raw-fish'] = 4, - ['rail'] = 16, - ['wood'] = 16 -} +--global.difficulty_tooltips = { +-- [1] = "Biters much less aggressive; pollution by train significantly lower; maps significantly more favourable; upgrades coin prices significantly cheaper; MK2 research enabled; flamer nerf more slight", +-- [2] = "Biters less aggressive; pollution by train lower; maps more favourable; upgrades coin prices cheaper; MK2 research enabled; flamer nerf more slight", +-- [3] = "Biters slightly less aggressive; pollution by train slightly lower; maps slightly more favourable; upgrades coin prices slightly cheaper; MK2 research enabled; flamer nerf more slight", +-- [4] = "Normal difficulty.", +-- [5] = "Biters more aggressive; pollution by train higher; maps less favourable; upgrades coin prices more expensive; flamer nerf less slight", +-- [6] = "Biters much more aggressive; pollution by train significantly higher; maps significantly less favourable; upgrades coin prices significantly more expensive; flamer nerf less slight", +-- [7] = "ENTER AT YOUR PERIL", +--} local function generate_overworld(surface, optplanet) - local objective = Chrono_table.get_table() - Planets.determine_planet(optplanet) - local planet = objective.planet - local message = { - 'chronosphere.planet_jump', - planet[1].name.name, - planet[1].ore_richness.name, - planet[1].day_speed.name - } - game.print(message, {r = 0.98, g = 0.66, b = 0.22}) - local discordmessage = - 'Destination: ' .. - planet[1].name.dname .. - ', Ore Richness: ' .. planet[1].ore_richness.dname .. ', Daynight cycle: ' .. planet[1].day_speed.dname - Server.to_discord_embed(discordmessage) - if planet[1].name.id == 12 then - game.print({'chronosphere.message_choppy'}, {r = 0.98, g = 0.66, b = 0.22}) - elseif planet[1].name.id == 14 then - game.print({'chronosphere.message_lava'}, {r = 0.98, g = 0.66, b = 0.22}) - elseif planet[1].name.id == 17 then - game.print({'chronosphere.message_fishmarket1'}, {r = 0.98, g = 0.66, b = 0.22}) - game.print({'chronosphere.message_fishmarket2'}, {r = 0.98, g = 0.66, b = 0.22}) - end - surface.min_brightness = 0 - surface.brightness_visual_weights = {1, 1, 1} - objective.surface = surface - surface.daytime = planet[1].time - local timer = planet[1].day_speed.timer - if timer == 0 then - surface.freeze_daytime = true - timer = timer + 1 - else - surface.freeze_daytime = false - end - surface.ticks_per_day = timer * 250 + local objective = Chrono_table.get_table() + Planets.determine_planet(optplanet) + local planet = objective.planet - local moisture = planet[1].name.moisture - if moisture ~= 0 then - local mgs = surface.map_gen_settings - mgs.property_expression_names['control-setting:moisture:bias'] = moisture - surface.map_gen_settings = mgs - end - if planet[1].name.id == 14 then --lava planet - local mgs = surface.map_gen_settings - mgs.water = 0 - surface.map_gen_settings = mgs - end - if planet[1].name.id ~= 12 then --choppy planet - local mgs = surface.map_gen_settings - mgs.water = 0.2 - surface.map_gen_settings = mgs - end - if planet[1].name.id == 17 then --fish market - local mgs = surface.map_gen_settings - mgs.width = 2176 - surface.map_gen_settings = mgs - surface.request_to_generate_chunks({-960, -64}, 0.5) - surface.force_generate_chunk_requests() - end + local message = {"chronosphere.planet_jump", planet[1].type.name, planet[1].ore_richness.name, planet[1].day_speed.name} + game.print(message, {r=0.98, g=0.66, b=0.22}) + + local discordmessage = "Destination: "..planet[1].type.dname..", Ore Richness: "..planet[1].ore_richness.dname..", Day length: "..planet[1].day_speed.dname + Server.to_discord_embed(discordmessage) + if planet[1].type.id == 12 then + game.print({"chronosphere.message_choppy"}, {r=0.98, g=0.66, b=0.22}) + elseif planet[1].type.id == 14 then + game.print({"chronosphere.message_lava"}, {r=0.98, g=0.66, b=0.22}) + elseif planet[1].type.id == 17 then + game.print({"chronosphere.message_fishmarket1"}, {r=0.98, g=0.66, b=0.22}) + game.print({"chronosphere.message_fishmarket2"}, {r=0.98, g=0.66, b=0.22}) + end + surface.min_brightness = 0 + surface.brightness_visual_weights = {1, 1, 1} + objective.surface = surface + surface.daytime = planet[1].time + local timer = planet[1].day_speed.timer + if timer == 0 then + surface.freeze_daytime = true + timer = timer + 1 + else + surface.freeze_daytime = false + end + surface.ticks_per_day = timer * 250 + + local moisture = planet[1].type.moisture + if moisture ~= 0 then + local mgs = surface.map_gen_settings + mgs.property_expression_names["control-setting:moisture:bias"] = moisture + surface.map_gen_settings = mgs + end + if planet[1].type.id == 14 then --lava planet + local mgs = surface.map_gen_settings + mgs.water = 0 + surface.map_gen_settings = mgs + end + if planet[1].type.id ~= 12 then --choppy planet + local mgs = surface.map_gen_settings + mgs.water = 0.2 + surface.map_gen_settings = mgs + end + if planet[1].type.id == 17 then --fish market + local mgs = surface.map_gen_settings + mgs.width = 2176 + surface.map_gen_settings = mgs + surface.request_to_generate_chunks({-960,-64}, 0.5) + surface.force_generate_chunk_requests() + end end local function render_train_hp() - local objective = Chrono_table.get_table() - local surface = game.surfaces[objective.active_surface_index] - objective.health_text = - rendering.draw_text { - text = 'HP: ' .. objective.health .. ' / ' .. objective.max_health, - surface = surface, - target = objective.locomotive, - target_offset = {0, -2.5}, - color = objective.locomotive.color, - scale = 1.40, - font = 'default-game', - alignment = 'center', - scale_with_zoom = false - } - objective.caption = - rendering.draw_text { - text = "Comfylatron's ChronoTrain", - surface = surface, - target = objective.locomotive, - target_offset = {0, -4.25}, - color = objective.locomotive.color, - scale = 1.80, - font = 'default-game', - alignment = 'center', - scale_with_zoom = false - } + local objective = Chrono_table.get_table() + local surface = game.surfaces[objective.active_surface_index] + objective.health_text = rendering.draw_text{ + text = "HP: " .. objective.health .. " / " .. objective.max_health, + surface = surface, + target = objective.locomotive, + target_offset = {0, -2.5}, + color = objective.locomotive.color, + scale = 1.40, + font = "default-game", + alignment = "center", + scale_with_zoom = false + } + objective.caption = rendering.draw_text{ + text = "Comfylatron's ChronoTrain", + surface = surface, + target = objective.locomotive, + target_offset = {0, -4.25}, + color = objective.locomotive.color, + scale = 1.80, + font = "default-game", + alignment = "center", + scale_with_zoom = false + } end + local function reset_map() - local objective = Chrono_table.get_table() - for _, player in pairs(game.players) do - if player.controller_type == defines.controllers.editor then - player.toggle_map_editor() - end - end - if game.surfaces['chronosphere'] then - game.delete_surface(game.surfaces['chronosphere']) - end - if game.surfaces['cargo_wagon'] then - game.delete_surface(game.surfaces['cargo_wagon']) - end - for i = 13, 16, 1 do - objective.upgrades[i] = 0 - end - objective.computermessage = 0 - objective.chronojumps = 0 - Planets.determine_planet(nil) - local planet = objective.planet - if not objective.active_surface_index then - objective.active_surface_index = game.create_surface('chronosphere', Chrono.get_map_gen_settings()).index - else - game.forces.player.set_spawn_position({12, 10}, game.surfaces[objective.active_surface_index]) - objective.active_surface_index = - Reset.soft_reset_map( - game.surfaces[objective.active_surface_index], - Chrono.get_map_gen_settings(), - starting_items - ).index - end + local objective = Chrono_table.get_table() + for _,player in pairs(game.players) do + if player.controller_type == defines.controllers.editor then player.toggle_map_editor() end + end - local surface = game.surfaces[objective.active_surface_index] - generate_overworld(surface, planet) - Chrono.restart_settings() + if game.surfaces["chronosphere"] then game.delete_surface(game.surfaces["chronosphere"]) end + if game.surfaces["cargo_wagon"] then game.delete_surface(game.surfaces["cargo_wagon"]) end + for i = 13, 16, 1 do + objective.upgrades[i] = 0 + end + objective.computermessage = 0 + objective.chronojumps = 0 - game.forces.player.set_spawn_position({12, 10}, surface) - Locomotive.locomotive_spawn(surface, {x = 16, y = 10}, Chrono.get_wagons(true)) - render_train_hp() - game.reset_time_played() - Locomotive.create_wagon_room() - Event_functions.mining_buffs(nil) - if objective.game_won then - game.print({'chronosphere.message_game_won_restart'}, {r = 0.98, g = 0.66, b = 0.22}) - end - objective.game_lost = false - objective.game_won = false + Planets.determine_planet(nil) + local planet = objective.planet + if not objective.active_surface_index then + objective.active_surface_index = game.create_surface("chronosphere", Chrono.get_map_gen_settings()).index + else + game.forces.player.set_spawn_position({12, 10}, game.surfaces[objective.active_surface_index]) + objective.active_surface_index = Reset.soft_reset_map(game.surfaces[objective.active_surface_index], Chrono.get_map_gen_settings(), Balance.starting_items).index + end - --set_difficulty() + local surface = game.surfaces[objective.active_surface_index] + generate_overworld(surface, planet) + Chrono.restart_settings() + + game.forces.player.set_spawn_position({12, 10}, surface) + Locomotive.locomotive_spawn(surface, {x = 16, y = 10}, Chrono.get_wagons(true)) + render_train_hp() + game.reset_time_played() + Locomotive.create_wagon_room() + Event_functions.mining_buffs(nil) + if objective.game_won then + game.print({"chronosphere.message_game_won_restart"}, {r=0.98, g=0.66, b=0.22}) + end + objective.game_lost = false + objective.game_won = false + + game.permissions.get_group("Default").set_allows_action(defines.input_action.grab_blueprint_record, false) + game.permissions.get_group("Default").set_allows_action(defines.input_action.import_blueprint_string, false) + game.permissions.get_group("Default").set_allows_action(defines.input_action.import_blueprint, false) end local function on_player_joined_game(event) - local objective = Chrono_table.get_table() - local player = game.players[event.player_index] - if not objective.flame_boots[event.player_index] then - objective.flame_boots[event.player_index] = {} - end - objective.flame_boots[event.player_index] = {fuel = 1} - if not objective.flame_boots[event.player_index].steps then - objective.flame_boots[event.player_index].steps = {} - end + local objective = Chrono_table.get_table() + local player = game.players[event.player_index] + if not objective.flame_boots[event.player_index] then + objective.flame_boots[event.player_index] = {} + end + objective.flame_boots[event.player_index] = {fuel = 1} + if not objective.flame_boots[event.player_index].steps then objective.flame_boots[event.player_index].steps = {} end - local surface = game.surfaces[objective.active_surface_index] + local surface = game.surfaces[objective.active_surface_index] - if player.online_time == 0 then - player.teleport( - surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 32, 0.5), - surface - ) - for item, amount in pairs(starting_items) do - player.insert({name = item, count = amount}) - end - end + if player.online_time == 0 then + player.teleport(surface.find_non_colliding_position("character", game.forces.player.get_spawn_position(surface), 32, 0.5), surface) + for item, amount in pairs(Balance.starting_items) do + player.insert({name = item, count = amount}) + end + end - if player.surface.index ~= objective.active_surface_index and player.surface.name ~= 'cargo_wagon' then - player.character = nil - player.set_controller({type = defines.controllers.god}) - player.create_character() - player.teleport( - surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 32, 0.5), - surface - ) - for item, amount in pairs(starting_items) do - player.insert({name = item, count = amount}) - end - end + if player.surface.index ~= objective.active_surface_index and player.surface.name ~= "cargo_wagon" then + player.character = nil + player.set_controller({type=defines.controllers.god}) + player.create_character() + player.teleport(surface.find_non_colliding_position("character", game.forces.player.get_spawn_position(surface), 32, 0.5), surface) + for item, amount in pairs(starting_items) do + player.insert({name = item, count = amount}) + end + end - local tile = surface.get_tile(player.position) - if tile.valid then - if tile.name == 'out-of-map' then - player.teleport( - surface.find_non_colliding_position( - 'character', - game.forces.player.get_spawn_position(surface), - 32, - 0.5 - ), - surface - ) - end - end + local tile = surface.get_tile(player.position) + if tile.valid then + if tile.name == "out-of-map" then + player.teleport(surface.find_non_colliding_position("character", game.forces.player.get_spawn_position(surface), 32, 0.5), surface) + end + end end local function on_pre_player_left_game(event) - local objective = Chrono_table.get_table() - local player = game.players[event.player_index] - if player.controller_type == defines.controllers.editor then - player.toggle_map_editor() - end - if player.character then - objective.offline_players[#objective.offline_players + 1] = {index = event.player_index, tick = game.tick} - end + local objective = Chrono_table.get_table() + local player = game.players[event.player_index] + if player.controller_type == defines.controllers.editor then player.toggle_map_editor() end + if player.character then + objective.offline_players[#objective.offline_players + 1] = {index = event.player_index, tick = game.tick} + end end + local function set_objective_health(final_damage_amount) - if final_damage_amount == 0 then - return - end - local objective = Chrono_table.get_table() - objective.health = math_floor(objective.health - final_damage_amount) - if objective.health > objective.max_health then - objective.health = objective.max_health - end + if final_damage_amount == 0 then return end + local objective = Chrono_table.get_table() + objective.health = math_floor(objective.health - final_damage_amount) + if objective.health > objective.max_health then objective.health = objective.max_health end - if objective.health <= 0 then - Chrono.objective_died() - end - if objective.health < objective.max_health / 2 and final_damage_amount > 0 then - Upgrades.trigger_poison() - end - rendering.set_text(objective.health_text, 'HP: ' .. objective.health .. ' / ' .. objective.max_health) + if objective.health <= 0 then + Chrono.objective_died() + end + if objective.health < objective.max_health / 2 and final_damage_amount > 0 then + Upgrades.trigger_poison() + end + rendering.set_text(objective.health_text, "HP: " .. objective.health .. " / " .. objective.max_health) end +local function award_coins(count) + Locomotive.award_coins(count) +end + + function Public.chronojump(choice) - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - if objective.game_lost then - goto continue - end - Chrono.process_jump() + local objective = Chrono_table.get_table() - local oldsurface = game.surfaces[objective.active_surface_index] + if objective.chronojumps == 0 then + Difficulty.set_poll_closing_timeout(game.tick) + end - for _, player in pairs(game.players) do - if player.surface == oldsurface then - if player.controller_type == defines.controllers.editor then - player.toggle_map_editor() - end - local wagons = {objective.locomotive_cargo[1], objective.locomotive_cargo[2], objective.locomotive_cargo[3]} - Locomotive.enter_cargo_wagon(player, wagons[math.random(1, 3)]) - end - end - objective.lab_cells = {} - objective.active_surface_index = - game.create_surface('chronosphere' .. objective.chronojumps, Chrono.get_map_gen_settings()).index - local surface = game.surfaces[objective.active_surface_index] - --log("seed of new surface: " .. surface.map_gen_settings.seed) - local planet = objective.planet - if choice then - Planets.determine_planet(choice) - end - generate_overworld(surface, planet) + if objective.game_lost then goto continue end - game.forces.player.set_spawn_position({12, 10}, surface) + if objective.chronojumps <= 24 then + award_coins( + Balance.coin_reward_per_second_jumped_early(objective.chronochargesneeded / objective.passive_chronocharge_rate + objective.jump_countdown_length - objective.passivetimer, Difficulty.get().difficulty_vote_value) + ) + end - Locomotive.locomotive_spawn(surface, {x = 16, y = 10}, Chrono.get_wagons(false)) - --if objective.locomotive == nil then Locomotive.locomotive_spawn(surface, {x = 16, y = 10}, Chrono.get_wagons(false)) end - render_train_hp() - game.delete_surface(oldsurface) - Chrono.post_jump() - Event_functions.flamer_nerfs() - surface.pollute( - objective.locomotive.position, - 150 * (3 / (objective.upgrades[2] / 3 + 1)) * (1 + objective.chronojumps) * Diff.difficulty_vote_value - ) - ::continue:: + Chrono.process_jump() + + local oldsurface = game.surfaces[objective.active_surface_index] + + for _,player in pairs(game.players) do + if player.surface == oldsurface then + if player.controller_type == defines.controllers.editor then player.toggle_map_editor() end + local wagons = {objective.locomotive_cargo[1], objective.locomotive_cargo[2], objective.locomotive_cargo[3]} + Locomotive.enter_cargo_wagon(player, wagons[math.random(1,3)]) + end + end + objective.lab_cells = {} + objective.active_surface_index = game.create_surface("chronosphere" .. objective.chronojumps, Chrono.get_map_gen_settings()).index + local surface = game.surfaces[objective.active_surface_index] + --log("seed of new surface: " .. surface.map_gen_settings.seed) + local planet = objective.planet + if choice then + Planets.determine_planet(choice) + end + generate_overworld(surface, planet) + + game.forces.player.set_spawn_position({12, 10}, surface) + + Locomotive.locomotive_spawn(surface, {x = 16, y = 10}, Chrono.get_wagons(false)) + --if objective.locomotive == nil then Locomotive.locomotive_spawn(surface, {x = 16, y = 10}, Chrono.get_wagons(false)) end + render_train_hp() + game.delete_surface(oldsurface) + Chrono.post_jump() + Event_functions.flamer_nerfs() + + -- + local pos = objective.locomotive.position or {x=0,y=0} + local exterior_pollution = math_floor(Balance.post_jump_initial_pollution(objective.chronojumps, Difficulty.get().difficulty_vote_value)) + game.surfaces[objective.active_surface_index].pollute(pos, exterior_pollution) + game.pollution_statistics.on_flow("locomotive", exterior_pollution) + + ::continue:: end local tick_minute_functions = { - [300 * 2] = Ai.destroy_inactive_biters, - [300 * 3 + 30 * 0] = Ai.pre_main_attack, -- setup for main_attack - [300 * 3 + 30 * 1] = Ai.perform_main_attack, - [300 * 3 + 30 * 2] = Ai.perform_main_attack, - [300 * 3 + 30 * 3] = Ai.perform_main_attack, - [300 * 3 + 30 * 4] = Ai.perform_main_attack, - [300 * 3 + 30 * 5] = Ai.perform_main_attack, -- call perform_main_attack 7 times on different ticks - [300 * 4] = Ai.send_near_biters_to_objective, - [300 * 5] = Ai.wake_up_sleepy_groups - --[300] = Ai.rogue_group + + [300 * 2] = Ai.destroy_inactive_biters, + [300 * 3 + 30 * 0] = Ai.pre_main_attack, -- setup for main_attack + [300 * 3 + 30 * 1] = Ai.perform_main_attack, + [300 * 3 + 30 * 2] = Ai.perform_main_attack, + [300 * 3 + 30 * 3] = Ai.perform_main_attack, + [300 * 3 + 30 * 4] = Ai.perform_main_attack, + [300 * 3 + 30 * 5] = Ai.perform_main_attack, -- call perform_main_attack 7 times on different ticks + [300 * 4] = Ai.send_near_biters_to_objective, + [300 * 5] = Ai.wake_up_sleepy_groups, + --[300] = Ai.rogue_group + } -local function tick() - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - local tick = game.tick - if tick % 60 == 30 and objective.passivetimer < 64 then - local surface = game.surfaces[objective.active_surface_index] - if objective.planet[1].name.id == 17 then - surface.request_to_generate_chunks({-800, 0}, 3 + math_floor(objective.passivetimer / 5)) - else - surface.request_to_generate_chunks({0, 0}, 3 + math_floor(objective.passivetimer / 5)) - end - --surface.force_generate_chunk_requests() - end - if tick % 10 == 0 and objective.planet[1].name.id == 18 then - Tick_functions.spawn_poison() - end - if tick % 30 == 0 then - if tick % 600 == 0 then - Tick_functions.charge_chronosphere() - Tick_functions.transfer_pollution() - if objective.poisontimeout > 0 then - objective.poisontimeout = objective.poisontimeout - 1 - end - end - if tick % 1800 == 0 then - Locomotive.set_player_spawn_and_refill_fish() - set_objective_health(Tick_functions.repair_train()) - Upgrades.check_upgrades() - Tick_functions.boost_evolution() - if objective.config.offline_loot then - Tick_functions.offline_players() - end - end - local key = tick % 3600 - if tick_minute_functions[key] then - tick_minute_functions[key]() - end - if tick % 60 == 0 and objective.planet[1].name.id ~= 17 then - objective.chronotimer = objective.chronotimer + 1 - objective.passivetimer = objective.passivetimer + 1 - if objective.chronojumps > 0 then - if objective.locomotive ~= nil then - local surface = game.surfaces[objective.active_surface_index] - local pos = objective.locomotive.position or {x = 0, y = 0} - if surface and surface.valid then - game.surfaces[objective.active_surface_index].pollute( - pos, - (0.5 * objective.chronojumps) * (3 / (objective.upgrades[2] / 3 + 1)) * - Diff.difficulty_vote_value - ) - end - end - end - if objective.planet[1].name.id == 19 then - Tick_functions.dangertimer() - end - if Tick_functions.check_chronoprogress() then - Public.chronojump(nil) - end - end - if tick % 120 == 0 then - Tick_functions.move_items() - Tick_functions.output_items() - end - if objective.game_reset_tick then - if objective.game_reset_tick < tick then - objective.game_reset_tick = nil - reset_map() - end - return - end - Locomotive.fish_tag() - end - for _, player in pairs(game.connected_players) do - Gui.update_gui(player) - end +local function initiate_jump_countdown() + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + local length = Balance.generate_jump_countdown_length(difficulty) + + objective.jump_countdown_start_time = objective.passivetimer + objective.jump_countdown_length = length + game.print({"chronosphere.message_initiate_jump_countdown", length}, {r=0.98, g=0.66, b=0.22}) +end + +local function check_if_overstayed() + local objective = Chrono_table.get_table() + + if objective.passivetimer * objective.passive_chronocharge_rate > (objective.chronochargesneeded * 0.75) and objective.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) then + objective.overstaycount = objective.overstaycount + 1 + end +end + +function Public.add_chronocharge() + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + +end + +local function drain_accumulators() + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + if objective.passivetimer < 10 then return end + if objective.chronocharges >= objective.chronochargesneeded then return end + if not objective.accumulators then return end + if not objective.chronocharges then return end + if objective.planet[1].type.id == 17 or objective.planet[1].type.id == 19 then return end + local acus = objective.accumulators + if #acus < 1 then return end + for i = 1, #acus, 1 do + if not acus[i].valid or not objective.locomotive.valid then return end + local energy = acus[i].energy + if energy > 1010000 and objective.chronocharges < objective.chronochargesneeded then + acus[i].energy = acus[i].energy - 1000000 + + objective.chronocharges = objective.chronocharges + 1 + + if objective.locomotive ~= nil and objective.locomotive.valid then + + local pos = objective.locomotive.position or {x=0,y=0} + local exterior_pollution = Balance.pollution_per_MJ_actively_charged(objective.chronojumps, difficulty, objective.upgrades[2]) + game.surfaces[objective.active_surface_index].pollute(pos, exterior_pollution) + game.pollution_statistics.on_flow("locomotive", exterior_pollution) + + if objective.chronocharges == objective.chronochargesneeded then + check_if_overstayed() + initiate_jump_countdown() + end + end + end + end +end + +function Public.attempt_to_jump() + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + if 100 * math_random() <= Balance.misfire_percentage_chance(difficulty) then + game.print({"chronosphere.message_jump_misfire"}, {r=0.98, g=0.66, b=0.22}) + objective.jump_countdown_length = objective.jump_countdown_length + 15 + else + Public.chronojump(nil) + end +end + + +function Public.get_total_accu_charge() + local objective = Chrono_table.get_table() + local acus = objective.accumulators + local e = 0 + if #acus > 0 then + for i = 1,#acus,1 do + if acus[i].valid then + e = e + acus[i].energy + end + end + end + return e +end + + +local function tick() --only even ticks trigger + local objective = Chrono_table.get_table() + local tick = game.tick + + if tick % 60 == 30 and objective.passivetimer < 64 then + local surface = game.surfaces[objective.active_surface_index] + if objective.planet[1].type.id == 17 then + surface.request_to_generate_chunks({-800,0}, 3 + math_floor(objective.passivetimer / 5)) + else + surface.request_to_generate_chunks({0,0}, 3 + math_floor(objective.passivetimer / 5)) + end + --surface.force_generate_chunk_requests() + end + + if tick % 12 == 0 and objective.planet[1].type.id == 18 then + Tick_functions.spawn_poison() + end + if tick % 60 == 2 then + objective.accumulator_energy_history[1] = Public.get_total_accu_charge() + end + if tick % 60 == 56 then + objective.accumulator_energy_history[2] = Public.get_total_accu_charge() + end + + if objective.chronocharges < objective.chronochargesneeded and objective.planet[1].type.id ~= 17 then + local chronotimer_ticks_between_increase = math_floor(60 / objective.passive_chronocharge_rate / 2) * 2 --make sure it's even because you can't do things on odd ticks + + if tick % chronotimer_ticks_between_increase == 0 then + objective.chronocharges = objective.chronocharges + 1 + end + end + + if tick % 30 == 0 then + local difficulty = Difficulty.get().difficulty_vote_value + + if tick % 60 == 0 and objective.planet[1].type.id ~= 17 then + objective.passivetimer = objective.passivetimer + 1 + + if objective.planet[1].type.id == 19 then + Tick_functions.dangertimer() + end + + Tick_functions.realtime_events() + + if objective.locomotive ~= nil and objective.locomotive.valid then + if objective.jump_countdown_start_time == -1 then + if objective.chronocharges == objective.chronochargesneeded then + check_if_overstayed() + initiate_jump_countdown() + end + + local pos = objective.locomotive.position or {x=0,y=0} + local exterior_pollution = Balance.passive_pollution_rate(objective.chronojumps, difficulty, objective.upgrades[2]) + game.surfaces[objective.active_surface_index].pollute(pos, exterior_pollution) + game.pollution_statistics.on_flow("locomotive", exterior_pollution) + else + if objective.passivetimer == objective.jump_countdown_start_time + objective.jump_countdown_length then + Public.attempt_to_jump() + else + local pos = objective.locomotive.position or {x=0,y=0} + local exterior_pollution = Balance.countdown_pollution_rate(objective.chronojumps, Difficulty.get().difficulty_vote_value) + game.surfaces[objective.active_surface_index].pollute(pos, exterior_pollution) + -- game.pollution_statistics.on_flow("locomotive", exterior_pollution) + end + end + end + + end + + if tick % 60 == 0 then + drain_accumulators() + end + + if tick % 120 == 0 then + Tick_functions.move_items() + Tick_functions.output_items() + end + + if tick % 600 == 0 then + Tick_functions.ramp_evolution() + Upgrades.check_upgrades() + Tick_functions.transfer_pollution() + if objective.poisontimeout > 0 then + objective.poisontimeout = objective.poisontimeout - 1 + end + end + + if tick % 1800 == 0 then + Locomotive.set_player_spawn_and_refill_fish() + set_objective_health(Tick_functions.repair_train()) + if objective.config.offline_loot then + Tick_functions.offline_players() + end + end + + if tick % 1800 == 900 and objective.jump_countdown_start_time ~= -1 then + Ai.perform_main_attack() + end + + local key = tick % 3600 + if tick_minute_functions[key] then tick_minute_functions[key]() end + if objective.game_reset_tick then + if objective.game_reset_tick < tick then + objective.game_reset_tick = nil + reset_map() + end + return + end + Locomotive.fish_tag() + end + for _, player in pairs(game.connected_players) do Gui.update_gui(player) end end local function on_init() - local objective = Chrono_table.get_table() - local T = Map.Pop_info() - T.localised_category = 'chronosphere' - T.main_caption_color = {r = 150, g = 150, b = 0} - T.sub_caption_color = {r = 0, g = 150, b = 0} - objective.game_lost = true - objective.game_won = false - objective.offline_players = {} + local objective = Chrono_table.get_table() + local T = Map.Pop_info() + T.localised_category = "chronosphere" + T.main_caption_color = {r = 150, g = 150, b = 0} + T.sub_caption_color = {r = 0, g = 150, b = 0} + objective.game_lost = true + objective.game_won = false + objective.offline_players = {} - objective.config.offline_loot = true - objective.config.jumpfailure = true - game.create_force('scrapyard') - local mgs = game.surfaces['nauvis'].map_gen_settings - mgs.width = 16 - mgs.height = 16 - game.surfaces['nauvis'].map_gen_settings = mgs - game.surfaces['nauvis'].clear() - reset_map() - Chrono.init_setup() - --if game.surfaces["nauvis"] then game.delete_surface(game.surfaces["nauvis"]) end + objective.config.offline_loot = true + objective.config.jumpfailure = true + game.create_force("scrapyard") + local mgs = game.surfaces["nauvis"].map_gen_settings + mgs.width = 16 + mgs.height = 16 + game.surfaces["nauvis"].map_gen_settings = mgs + game.surfaces["nauvis"].clear() + + for k, v in pairs(Balance.player_ammo_damage_modifiers()) do + game.forces['player'].set_ammo_damage_modifier(k, v) + end + + for k, v in pairs(Balance.player_gun_speed_modifiers()) do + game.forces['player'].set_gun_speed_modifier(k, v) + end + + reset_map() + --if game.surfaces["nauvis"] then game.delete_surface(game.surfaces["nauvis"]) end end -- local function on_load() @@ -428,138 +541,108 @@ end -- end local function protect_entity(event) - local objective = Chrono_table.get_table() - if event.entity.force.index ~= 1 then - return - end --Player Force - if Event_functions.isprotected(event.entity) then - if event.cause then - if event.cause == objective.comfylatron or event.entity == objective.comfylatron then - return - end - if event.cause.force.index == 2 or event.cause.force.name == 'scrapyard' then - set_objective_health(event.final_damage_amount) - end - elseif objective.planet[1].name.id == 19 then - set_objective_health(event.final_damage_amount) - end - if not event.entity.valid then - return - end - event.entity.health = event.entity.health + event.final_damage_amount - end -end - -local function on_entity_damaged(event) - if not event.entity.valid then - return - end - protect_entity(event) - if not event.entity.valid then - return - end - if not event.entity.health then - return - end - Event_functions.biters_chew_rocks_faster(event) - if event.entity.force.name == 'enemy' then - Event_functions.biter_immunities(event) - end + local objective = Chrono_table.get_table() + if event.entity.force.index ~= 1 then return end --Player Force + if Event_functions.isprotected(event.entity) then + if event.cause then + if event.cause == objective.comfylatron or event.entity == objective.comfylatron then + return + end + if event.cause.force.index == 2 or event.cause.force.name == "scrapyard" then + set_objective_health(event.final_damage_amount) + end + elseif objective.planet[1].type.id == 19 then + set_objective_health(event.final_damage_amount) + end + if not event.entity.valid then return end + event.entity.health = event.entity.health + event.final_damage_amount + end end local function pre_player_mined_item(event) - local objective = Chrono_table.get_table() - if objective.planet[1].name.id == 11 then --rocky planet - if event.entity.name == 'rock-huge' or event.entity.name == 'rock-big' or event.entity.name == 'sand-rock-big' then - Event_functions.trap(event.entity, false) - event.entity.destroy() - Event_functions.rocky_loot(event) - end - end + local objective = Chrono_table.get_table() + if objective.planet[1].type.id == 11 then --rocky planet + if event.entity.name == "rock-huge" or event.entity.name == "rock-big" or event.entity.name == "sand-rock-big" then + Event_functions.trap(event.entity, false) + event.entity.destroy() + Event_functions.rocky_loot(event) + end + end end local function on_player_mined_entity(event) - local objective = Chrono_table.get_table() - local entity = event.entity - if not entity.valid then - return - end - if entity.type == 'tree' and objective.planet[1].name.id == 12 then --choppy planet - Event_functions.trap(entity, false) - Event_functions.choppy_loot(event) - end - if entity.name == 'rock-huge' or entity.name == 'rock-big' or entity.name == 'sand-rock-big' then - if objective.planet[1].name.id ~= 11 and objective.planet[1].name.id ~= 16 then --rocky and maze planet - Ores.prospect_ores(entity, entity.surface, entity.position) - elseif objective.planet[1].name.id == 11 then - event.buffer.clear() -- rocky planet - end - end + local objective = Chrono_table.get_table() + local entity = event.entity + if not entity.valid then return end + if entity.type == "tree" and objective.planet[1].type.id == 12 then --choppy planet + Event_functions.trap(entity, false) + Event_functions.choppy_loot(event) + end + if entity.name == "rock-huge" or entity.name == "rock-big" or entity.name == "sand-rock-big" then + if objective.planet[1].type.id ~= 11 and objective.planet[1].type.id ~= 16 then --rocky and maze planet + Ores.prospect_ores(entity, entity.surface, entity.position) + elseif + objective.planet[1].type.id == 11 then event.buffer.clear() -- rocky planet + end + end end local function on_entity_died(event) - local objective = Chrono_table.get_table() - if event.entity.type == 'tree' and objective.planet[1].name.id == 12 then --choppy planet - if event.cause then - if event.cause.valid then - if event.cause.force.name ~= 'enemy' then - Event_functions.trap(event.entity, false) - end - end - end - -- if not event.entity.valid then return end - -- for _, entity in pairs (event.entity.surface.find_entities_filtered({area = {{event.entity.position.x - 4, event.entity.position.y - 4},{event.entity.position.x + 4, event.entity.position.y + 4}}, name = "fire-flame-on-tree"})) do - -- if entity.valid then entity.destroy() end - -- end - --return - end - local entity = event.entity - if not entity.valid then - return - end - if entity.type == 'unit' and entity.force == 'enemy' then - objective.active_biters[entity.unit_number] = nil - end - if entity.type == 'rocket-silo' and entity.force.name == 'enemy' then - Event_functions.danger_silo(entity) - end - if entity.force.name == 'scrapyard' and entity.name == 'gun-turret' then - if objective.planet[1].name.id == 19 or objective.planet[1].name.id == 16 then --danger + hedge maze - Event_functions.trap(entity, true) - end - end - if entity.force.name == 'enemy' then - if entity.type == 'unit-spawner' then - Event_functions.spawner_loot(entity.surface, entity.position) - if objective.planet[1].name.id == 18 then - Ores.prospect_ores(entity, entity.surface, entity.position) - end - else - if objective.planet[1].name.id == 18 then - Event_functions.swamp_loot(event) - end - end - end - if entity.force.index == 3 then - if event.cause then - if event.cause.valid then - if event.cause.force.index == 2 then - Event_functions.shred_simple_entities(entity) - end - end - end - end -end - -local function on_research_finished(event) - Event_functions.flamer_nerfs() - Event_functions.mining_buffs(event) + local objective = Chrono_table.get_table() + if event.entity.type == "tree" and objective.planet[1].type.id == 12 then --choppy planet + if event.cause then + if event.cause.valid then + if event.cause.force.name ~= "enemy" then + Event_functions.trap(event.entity, false) + end + end + end + -- if not event.entity.valid then return end + -- for _, entity in pairs (event.entity.surface.find_entities_filtered({area = {{event.entity.position.x - 4, event.entity.position.y - 4},{event.entity.position.x + 4, event.entity.position.y + 4}}, name = "fire-flame-on-tree"})) do + -- if entity.valid then entity.destroy() end + -- end + --return + end + local entity = event.entity + if not entity.valid then return end + if entity.type == "unit" and entity.force == "enemy" then + objective.active_biters[entity.unit_number] = nil + end + if entity.type == "rocket-silo" and entity.force.name == "enemy" then + Event_functions.danger_silo(entity) + end + if entity.force.name == "scrapyard" and entity.name == "gun-turret" then + if objective.planet[1].type.id == 19 or objective.planet[1].type.id == 16 then --danger + hedge maze + Event_functions.trap(entity, true) + end + end + if entity.force.name == "enemy" then + if entity.type == "unit-spawner" then + Event_functions.spawner_loot(entity.surface, entity.position) + if objective.planet[1].type.id == 18 then + Ores.prospect_ores(entity, entity.surface, entity.position) + end + else + if objective.planet[1].type.id == 18 then + Event_functions.swamp_loot(event) + end + end + end + if entity.force.index == 3 then + if event.cause then + if event.cause.valid then + if event.cause.force.index == 2 then + Event_functions.shred_simple_entities(entity) + end + end + end + end end local function on_player_driving_changed_state(event) - local player = game.players[event.player_index] - local vehicle = event.entity - Locomotive.enter_cargo_wagon(player, vehicle) + local player = game.players[event.player_index] + local vehicle = event.entity + Locomotive.enter_cargo_wagon(player, vehicle) end -- function deny_building(event) @@ -601,16 +684,80 @@ end -- end local function on_player_changed_position(event) - local objective = Chrono_table.get_table() - if objective.planet[1].name.id == 14 then --lava planet - Event_functions.lava_planet(event) - end + local objective = Chrono_table.get_table() + if objective.planet[1].type.id == 14 then --lava planet + Event_functions.lava_planet(event) + end end local function on_technology_effects_reset(event) - Event_functions.on_technology_effects_reset(event) + Event_functions.on_technology_effects_reset(event) end +local function on_research_finished(event) + local difficulty = Difficulty.get().difficulty_vote_value + + Event_functions.flamer_nerfs() + Event_functions.mining_buffs(event) + + local research = event.research + local p_force = research.force + + for _, e in ipairs(research.effects) do + local t = e.type + if t == 'ammo-damage' then + local category = e.ammo_category + local factor = Balance.player_ammo_damage_modifiers()[category] or 0 + + if factor then + local current_m = p_force.get_ammo_damage_modifier(category) + local m = e.modifier + p_force.set_ammo_damage_modifier(category, current_m + factor * m) + end + elseif t == 'gun-speed' then + local category = e.ammo_category + local factor = Balance.player_gun_speed_modifiers()[category] or 0 + + if factor then + local current_m = p_force.get_gun_speed_modifier(category) + local m = e.modifier + p_force.set_gun_speed_modifier(category, current_m + factor * m) + end + end + end + +end + +local function on_entity_damaged(event) + local difficulty = Difficulty.get().difficulty_vote_value + + if not event.entity.valid then return end + protect_entity(event) + if not event.entity.valid then return end + if not event.entity.health then return end + Event_functions.biters_chew_rocks_faster(event) + if event.entity.force.name == "enemy" then + Event_functions.biter_immunities(event) + end + + if not event.cause then return end + if not event.cause.valid then return end + if event.cause.name ~= "character" then return end + if event.damage_type.name ~= "physical" then return end + + local player = event.cause + if player.shooting_state.state == defines.shooting.not_shooting then return end + local weapon = player.get_inventory(defines.inventory.character_guns)[player.selected_gun_index] + local ammo = player.get_inventory(defines.inventory.character_ammo)[player.selected_gun_index] + if not weapon.valid_for_read or not ammo.valid_for_read then return end + if weapon.name ~= "pistol" then return end + if ammo.name ~= "firearm-magazine" and ammo.name ~= "piercing-rounds-magazine" and ammo.name ~= "uranium-rounds-magazine" then return end + if not event.entity.valid then return end + event.entity.damage(event.final_damage_amount * (Balance.pistol_damage_multiplier(difficulty) - 1), player.force, "impact", player) +end + + + local event = require 'utils.event' event.on_init(on_init) event.on_load(on_load) @@ -627,35 +774,35 @@ event.add(defines.events.on_player_changed_position, on_player_changed_position) event.add(defines.events.on_technology_effects_reset, on_technology_effects_reset) event.add(defines.events.on_gui_click, Gui.on_gui_click) + if _DEBUG then - local Session = require 'utils.session_data' - local Color = require 'utils.color_presets' + local Session = require 'utils.session_data' + local Color = require 'utils.color_presets' - commands.add_command( - 'chronojump', - 'Weeeeee!', - function(cmd) - local player = game.player - local trusted = Session.get_trusted_table() - local param = tostring(cmd.parameter) - local p + commands.add_command( + 'chronojump', + 'Weeeeee!', + function(cmd) + local player = game.player + local trusted = Session.get_trusted_table() + local param = tostring(cmd.parameter) + local p - if player then - if player ~= nil then - p = player.print - if not trusted[player.name] then - if not player.admin then - p('[ERROR] Only admins and trusted weebs are allowed to run this command!', Color.fail) - return - end - end - else - p = log - end - end - Public.chronojump(param) - end - ) + if player then + if player ~= nil then + p = player.print + if not trusted[player.name] then + if not player.admin then + p("[ERROR] Only admins and trusted weebs are allowed to run this command!", Color.fail) + return + end + end + else + p = log + end + end + Public.chronojump(param) + end) end --Time for the debug code. If any (not global.) globals are written to at this point, an error will be thrown. --eg, x = 2 will throw an error because it's not global.x or local x diff --git a/maps/chronosphere/ores.lua b/maps/chronosphere/ores.lua index 1b81445c..55b2619d 100644 --- a/maps/chronosphere/ores.lua +++ b/maps/chronosphere/ores.lua @@ -1,8 +1,10 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' local Public_ores = {} local simplex_noise = require 'utils.simplex_noise'.d2 local math_random = math.random local math_floor = math.floor +local math_ceil = math.ceil local function draw_noise_ore_patch(position, name, surface, radius, richness, mixed) if not position then return end @@ -24,17 +26,25 @@ local function draw_noise_ore_patch(position, name, surface, radius, richness, m noise = noise_1 + noise_2 * 0.12 local distance_to_center = math.sqrt(x^2 + y^2) local a = richness - richness_part * distance_to_center - if distance_to_center < radius - math.abs(noise * radius * 0.85) and a > 1 then - pos = surface.find_non_colliding_position(name, pos, 64, 1, true) - if not pos then return end + if distance_to_center < radius - math.abs(noise * radius * 0.85) and a > 1 then + if mixed then noise = simplex_noise(pos.x * 0.005, pos.y * 0.005, seed) + simplex_noise(pos.x * 0.01, pos.y * 0.01, seed) * 0.3 + simplex_noise(pos.x * 0.05, pos.y * 0.05, seed) * 0.2 local i = (math_floor(noise * 100) % 7) + 1 name = ore_raffle[i] end local entity = {name = name, position = pos, amount = a} - if surface.can_place_entity(entity) then + + local preexisting_ores = surface.find_entities_filtered{area = {{pos.x - 0.025, pos.y - 0.025}, {pos.x + 0.025, pos.y + 0.025}}, type= "resource"} + + if #preexisting_ores >= 1 then surface.create_entity(entity) + else + pos = surface.find_non_colliding_position(name, pos, 64, 1, true) + if not pos then return end + if surface.can_place_entity(entity) then + surface.create_entity(entity) + end end end end @@ -44,17 +54,17 @@ end local function get_size_of_ore(ore, planet) local base_size = math_random(5, 10) + math_floor(planet[1].ore_richness.factor * 3) local final_size - if planet[1].name.id == 1 and ore == "iron-ore" then --iron planet + if planet[1].type.id == 1 and ore == "iron-ore" then --iron planet final_size = math_floor(base_size * 1.5) - elseif planet[1].name.id == 2 and ore == "copper-ore" then --copper planet + elseif planet[1].type.id == 2 and ore == "copper-ore" then --copper planet final_size = math_floor(base_size * 1.5) - elseif planet[1].name.id == 3 and ore == "stone" then --stone planet + elseif planet[1].type.id == 3 and ore == "stone" then --stone planet final_size = math_floor(base_size * 1.5) - elseif planet[1].name.id == 9 and ore == "coal" then --coal planet + elseif planet[1].type.id == 9 and ore == "coal" then --coal planet final_size = math_floor(base_size * 1.5) - elseif planet[1].name.id == 5 and ore == "uranium-ore" then --uranium planet + elseif planet[1].type.id == 5 and ore == "uranium-ore" then --uranium planet final_size = math_floor(base_size * 1.5) - elseif planet[1].name.id == 6 then --mixed planet + elseif planet[1].type.id == 6 then --mixed planet final_size = base_size else final_size = math_floor(base_size / 2) @@ -65,21 +75,21 @@ end local function get_oil_amount(pos, oil_w, richness) local objective = Chrono_table.get_table() local hundred_percent = 300000 - return (hundred_percent / 50) * (1+objective.chronojumps) * oil_w * richness + return math_ceil((hundred_percent / 100) * (4 + objective.chronojumps) * oil_w * richness / 3) end local function spawn_ore_vein(surface, pos, planet) local objective = Chrono_table.get_table() local mixed = false - if planet[1].name.id == 6 then mixed = true end --mixed planet + if planet[1].type.id == 6 then mixed = true end --mixed planet local richness = math_random(50 + 10 * objective.chronojumps, 100 + 10 * objective.chronojumps) * planet[1].ore_richness.factor - if planet[1].name.id == 16 then richness = richness * 10 end --hedge maze - local iron = {w = planet[1].name.iron, t = planet[1].name.iron} - local copper = {w = planet[1].name.copper, t = iron.t + planet[1].name.copper} - local stone = {w = planet[1].name.stone, t = copper.t + planet[1].name.stone} - local coal = {w = planet[1].name.coal, t = stone.t + planet[1].name.coal} - local uranium = {w = planet[1].name.uranium, t = coal.t + planet[1].name.uranium} - local oil = {w = planet[1].name.oil, t = uranium.t + planet[1].name.oil} + if planet[1].type.id == 16 then richness = richness * 10 end --hedge maze + local iron = {w = planet[1].type.iron, t = planet[1].type.iron} + local copper = {w = planet[1].type.copper, t = iron.t + planet[1].type.copper} + local stone = {w = planet[1].type.stone, t = copper.t + planet[1].type.stone} + local coal = {w = planet[1].type.coal, t = stone.t + planet[1].type.coal} + local uranium = {w = planet[1].type.uranium, t = coal.t + planet[1].type.uranium} + local oil = {w = planet[1].type.oil, t = uranium.t + planet[1].type.oil} local roll = math_random (0, oil.t) if roll == 0 then return end @@ -100,9 +110,9 @@ local function spawn_ore_vein(surface, pos, planet) --if surface.can_place_entity({name = choice, position = pos, amount = 1}) then if choice == "crude-oil" then - surface.create_entity({name = "crude-oil", position = pos, amount = get_oil_amount(pos, oil.w, planet[1].ore_richness.factor) / 2 }) + surface.create_entity({name = "crude-oil", position = pos, amount = get_oil_amount(pos, oil.w, planet[1].ore_richness.factor) }) else - draw_noise_ore_patch(pos, choice, surface, get_size_of_ore(choice, planet), richness / 2, mixed) + draw_noise_ore_patch(pos, choice, surface, get_size_of_ore(choice, planet), richness * 0.75, mixed) end --end end @@ -114,7 +124,7 @@ function Public_ores.prospect_ores(entity, surface, pos) if entity then if entity.name == "rock-huge" then chance = 40 end if entity.type == "unit-spawner" then chance = 40 end - if planet[1].name.id == 15 then chance = chance + 30 end + if planet[1].type.id == 15 then chance = chance + 30 end if math_random(chance + math_floor(10 * planet[1].ore_richness.factor) ,100 + chance) >= 100 then spawn_ore_vein(surface, pos, planet) end @@ -123,4 +133,164 @@ function Public_ores.prospect_ores(entity, surface, pos) end end -return Public_ores + + +---- SCRAP ---- + + + + +local scrap_yield_amounts = { + ["iron-plate"] = 8, + ["iron-gear-wheel"] = 4, + ["iron-stick"] = 8, + ["copper-plate"] = 8, + ["copper-cable"] = 12, + ["electronic-circuit"] = 4, + ["steel-plate"] = 4, + ["pipe"] = 4, + ["solid-fuel"] = 4, + ["empty-barrel"] = 3, + ["crude-oil-barrel"] = 3, + ["lubricant-barrel"] = 3, + ["petroleum-gas-barrel"] = 3, + ["heavy-oil-barrel"] = 3, + ["light-oil-barrel"] = 3, + ["water-barrel"] = 3, + ["grenade"] = 3, + ["battery"] = 3, + ["explosives"] = 3, + ["advanced-circuit"] = 3, + ["nuclear-fuel"] = 0.1, + ["pipe-to-ground"] = 1, + ["plastic-bar"] = 3, + ["processing-unit"] = 1, + ["used-up-uranium-fuel-cell"] = 1, + ["uranium-fuel-cell"] = 0.3, + ["rocket-fuel"] = 0.3, + ["rocket-control-unit"] = 0.3, + ["low-density-structure"] = 0.3, + ["heat-pipe"] = 1, + ["green-wire"] = 8, + ["red-wire"] = 8, + ["engine-unit"] = 2, + ["electric-engine-unit"] = 2, + ["logistic-robot"] = 0.3, + ["construction-robot"] = 0.3, + ["land-mine"] = 1, + ["rocket"] = 2, + ["explosive-rocket"] = 2, + ["cannon-shell"] = 2, + ["explosive-cannon-shell"] = 2, + ["uranium-cannon-shell"] = 2, + ["explosive-uranium-cannon-shell"] = 2, + ["artillery-shell"] = 0.3, + ["cluster-grenade"] = 0.3, + ["defender-capsule"] = 2, + ["destroyer-capsule"] = 0.3, + ["distractor-capsule"] = 0.3 +} + +local scrap_mining_chance_weights = { + {name = "iron-plate", chance = 600}, + {name = "iron-gear-wheel", chance = 400}, + {name = "copper-plate", chance = 400}, + {name = "copper-cable", chance = 200}, + {name = "electronic-circuit", chance = 150}, + {name = "steel-plate", chance = 100}, + {name = "pipe", chance = 75}, + {name = "iron-stick", chance = 30}, + {name = "solid-fuel", chance = 20}, + {name = "battery", chance = 10}, + {name = "crude-oil-barrel", chance = 10}, + {name = "petroleum-gas-barrel", chance = 7}, + {name = "heavy-oil-barrel", chance = 7}, + {name = "light-oil-barrel", chance = 7}, + {name = "lubricant-barrel", chance = 4}, + {name = "empty-barrel", chance = 4}, + {name = "water-barrel", chance = 4}, + {name = "green-wire", chance = 4}, + {name = "red-wire", chance = 4}, + {name = "grenade", chance = 3}, + {name = "pipe-to-ground", chance = 3}, + {name = "explosives", chance = 3}, + {name = "advanced-circuit", chance = 3}, + {name = "plastic-bar", chance = 3}, + {name = "engine-unit", chance = 2}, + {name = "nuclear-fuel", chance = 1}, + {name = "processing-unit", chance = 1}, + {name = "used-up-uranium-fuel-cell", chance = 1}, + {name = "uranium-fuel-cell", chance = 1}, + {name = "rocket-fuel", chance = 1}, + {name = "rocket-control-unit", chance = 1}, + {name = "low-density-structure", chance = 1}, + {name = "heat-pipe", chance = 1}, + {name = "electric-engine-unit", chance = 1}, + {name = "logistic-robot", chance = 1}, + {name = "construction-robot", chance = 1}, + {name = "land-mine", chance = 1}, + {name = "rocket", chance = 1}, + {name = "explosive-rocket", chance = 1}, + {name = "cannon-shell", chance = 1}, + {name = "explosive-cannon-shell", chance = 1}, + {name = "uranium-cannon-shell", chance = 1}, + {name = "explosive-uranium-cannon-shell", chance = 1}, + {name = "artillery-shell", chance = 1}, + {name = "cluster-grenade", chance = 1}, + {name = "defender-capsule", chance = 1}, + {name = "destroyer-capsule", chance = 1}, + {name = "distractor-capsule", chance = 1} +} + + + + +local scrap_raffle = {} +for _, t in pairs (scrap_mining_chance_weights) do + for x = 1, t.chance, 1 do + table.insert(scrap_raffle, t.name) + end +end + +local size_of_scrap_raffle = #scrap_raffle + + + +local function on_player_mined_entity(event) + local entity = event.entity + if not entity.valid then return end + if entity.name ~= "mineable-wreckage" then return end + + event.buffer.clear() + + local scrap = scrap_raffle[math.random(1, size_of_scrap_raffle)] + + + local amount_bonus_multiplier = Balance.scrap_quantity_multiplier(game.forces.enemy.evolution_factor) + + local r1 = math.ceil(scrap_yield_amounts[scrap] * 0.3 * amount_bonus_multiplier) + local r2 = math.ceil(scrap_yield_amounts[scrap] * 1.7 * amount_bonus_multiplier) + local amount = math.random(r1, r2) + + local player = game.players[event.player_index] + local inserted_count = player.insert({name = scrap, count = amount}) + + if inserted_count ~= amount then + local amount_to_spill = amount - inserted_count + entity.surface.spill_item_stack(entity.position,{name = scrap, count = amount_to_spill}, true) + end + + entity.surface.create_entity({ + name = "flying-text", + position = entity.position, + text = "+" .. amount .. " [img=item/" .. scrap .. "]", + color = {r=0.98, g=0.66, b=0.22} + }) +end + +local Event = require 'utils.event' +Event.add(defines.events.on_player_mined_entity, on_player_mined_entity) + + + +return Public_ores \ No newline at end of file diff --git a/maps/chronosphere/random.lua b/maps/chronosphere/random.lua new file mode 100644 index 00000000..54392464 --- /dev/null +++ b/maps/chronosphere/random.lua @@ -0,0 +1,37 @@ +local math_random = math.random +local Public = {} + +function Public.shuffle(tbl) + local size = #tbl + for i = size, 1, -1 do + local rand = math_random(size) + tbl[i], tbl[rand] = tbl[rand], tbl[i] + end + return tbl +end + + +function Public.raffle(values,weights) --arguments of the form {[a] = A, [b] = B, ...} and {[a] = a_weight, [b] = b_weight, ...} or just {a,b,c,...} and {1,2,3...} + + local total_weight = 0 + for k,w in pairs(weights) do + assert(values[k]) + if w > 0 then + total_weight = total_weight + w + end + -- negative weights treated as zero + end + assert(total_weight > 0) + + local cumulative_probability = 0 + local rng = math_random() + for k,v in pairs(values) do + assert(weights[k]) + cumulative_probability = cumulative_probability + (weights[k] / total_weight) + if rng <= cumulative_probability then + return v + end + end +end + +return Public \ No newline at end of file diff --git a/maps/chronosphere/table.lua b/maps/chronosphere/table.lua index b4da60ad..cf5b7e3b 100644 --- a/maps/chronosphere/table.lua +++ b/maps/chronosphere/table.lua @@ -1,4 +1,4 @@ --- on table to rule them all! +-- one table to rule them all! local Global = require 'utils.global' local Event = require 'utils.event' @@ -23,18 +23,22 @@ function Public.reset_table() chronosphere.chronojumps = 0 chronosphere.game_lost = true chronosphere.game_won = false - chronosphere.max_health = 10000 - chronosphere.health = 10000 + chronosphere.max_health = 0 + chronosphere.health = 0 chronosphere.poisontimeout = 0 - chronosphere.chronotimer = 0 + chronosphere.chronocharges = 0 + chronosphere.passive_chronocharge_rate = 0 + chronosphere.accumulator_energy_history = {} chronosphere.passivetimer = 0 - chronosphere.passivejumps = 0 - chronosphere.chrononeeds = 2000 + chronosphere.overstaycount = 0 + chronosphere.chronochargesneeded = 0 + chronosphere.jump_countdown_start_time = 0 + chronosphere.jump_countdown_length = 0 chronosphere.mainscore = 0 chronosphere.active_biters = {} chronosphere.unit_groups = {} chronosphere.biter_raffle = {} - chronosphere.dangertimer = 1200 + chronosphere.dangertimer = 0 chronosphere.dangers = {} chronosphere.looted_nukes = 0 chronosphere.offline_players = {} @@ -44,7 +48,7 @@ function Public.reset_table() chronosphere.upgradechest = {} chronosphere.fishchest = {} chronosphere.comfylatron = {} - chronosphere.acumulators = {} + chronosphere.accumulators = {} chronosphere.comfychests = {} chronosphere.comfychests2 = {} chronosphere.locomotive_cargo = {} diff --git a/maps/chronosphere/terrain.lua b/maps/chronosphere/terrain.lua index 573581e3..b8f18634 100644 --- a/maps/chronosphere/terrain.lua +++ b/maps/chronosphere/terrain.lua @@ -78,17 +78,17 @@ end local function get_size_of_ore(ore, planet) local base_size = 0.04 + 0.04 * planet[1].ore_richness.factor local final_size = 1 - if planet[1].name.id == 1 and ore == "iron-ore" then --iron planet + if planet[1].type.id == 1 and ore == "iron-ore" then --iron planet final_size = base_size * 5 - elseif planet[1].name.id == 2 and ore == "copper-ore" then --copper planet + elseif planet[1].type.id == 2 and ore == "copper-ore" then --copper planet final_size = base_size * 5 - elseif planet[1].name.id == 3 and ore == "stone" then --stone planet + elseif planet[1].type.id == 3 and ore == "stone" then --stone planet final_size = base_size * 5 - elseif planet[1].name.id == 9 and ore == "coal" then --coal planet + elseif planet[1].type.id == 9 and ore == "coal" then --coal planet final_size = base_size * 5 - elseif planet[1].name.id == 5 and ore == "uranium-ore" then --uranium planet + elseif planet[1].type.id == 5 and ore == "uranium-ore" then --uranium planet final_size = base_size * 5 - elseif planet[1].name.id == 6 then --mixed planet + elseif planet[1].type.id == 6 then --mixed planet final_size = base_size * 2 else final_size = base_size / 2 @@ -185,7 +185,7 @@ end local function process_hedgemaze_position(p, seed, tiles, entities, treasure, planet, cell, things) --local labyrinth_cell_size = 16 --valid values are 2, 4, 8, 16, 32 - local biters = planet[1].name.biters + local biters = planet[1].type.biters local mazenoise = get_noise("hedgemaze", {x = p.x - p.x % labyrinth_cell_size, y = p.y - p.y % labyrinth_cell_size}, seed) if mazenoise < lake_noise_value and math_sqrt((p.x - p.x % labyrinth_cell_size)^2 + (p.y - p.y % labyrinth_cell_size)^2) > 65 then @@ -196,23 +196,24 @@ local function process_hedgemaze_position(p, seed, tiles, entities, treasure, pl if cell then --path if things then if things == "lake" and p.x % 32 > 8 and p.x % 32 < 24 and p.y % 32 > 8 and p.y % 32 < 24 then - tiles[#tiles + 1] = {name = "water", position = p} - return + tiles[#tiles + 1] = {name = "water", position = p} return elseif things == "prospect" then if math_random(1,252 - biters) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 300 then entities[#entities + 1] = {name = spawner_raffle[math_random(1, 4)], position = p} end elseif things == "camp" then - if p.x % 32 > 12 and p.x % 32 < 20 and p.y % 32 > 12 and p.y % 32 < 20 and math_random(1,6) == 1 then - treasure[#treasure + 1] = p + if p.x % 32 > 12 and p.x % 32 < 20 and p.y % 32 > 12 and p.y % 32 < 20 then + if math_random(1,16) == 1 then treasure[#treasure + 1] = p end + elseif p.x % 32 == 11 or p.x % 32 == 12 or p.y % 32 == 11 or p.y % 32 == 12 or p.x % 32 == 21 or p.x % 32 == 20 or p.y % 32 == 21 or p.y % 32 == 20 then + if math_random(1,28) == 1 then entities[#entities + 1] = {name = "land-mine", position = p, force = "scrapyard"} end end elseif things == "crashsite" then if math_random(1,10) == 1 then entities[#entities + 1] = {name="mineable-wreckage", position=p} end elseif things == "treasure" then - local roll = math_random(1,128) - if roll == 1 then + local roll = math_random(1,512) + if roll <= 2 then treasure[#treasure + 1] = p - elseif roll == 2 then + elseif roll == 3 then entities[#entities + 1] = {name = "land-mine", position = p, force = "scrapyard"} end end @@ -240,7 +241,7 @@ local function process_hedgemaze_position(p, seed, tiles, entities, treasure, pl elseif things == "prospect" then if math_random(1,252 - biters) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 300 then entities[#entities + 1] = {name = spawner_raffle[math_random(1, 4)], position = p} end elseif things == "camp" then - if p.x % 32 > 12 and p.x % 32 < 20 and p.y % 32 > 12 and p.y % 32 < 20 and math_random(1,6) == 1 then + if p.x % 32 > 12 and p.x % 32 < 20 and p.y % 32 > 12 and p.y % 32 < 20 and math_random(1,16) == 1 then treasure[#treasure + 1] = p end elseif things == "crashsite" then @@ -248,12 +249,15 @@ local function process_hedgemaze_position(p, seed, tiles, entities, treasure, pl entities[#entities + 1] = {name="mineable-wreckage", position=p} end elseif things == "treasure" then - if math_random(1,128) == 1 then + if math_random(1,256) == 1 then treasure[#treasure + 1] = p end end else - if math_random(1, 150) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 200 then + if math_random(1, 2 * 1024) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 125 then + entities[#entities + 1] = {name = worm_raffle[math_random(1 + math_floor(game.forces["enemy"].evolution_factor * 8), math_floor(1 + game.forces["enemy"].evolution_factor * 16))], position = p} + elseif math_random(1, 4 * 1024) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 150 then treasure[#treasure + 1] = p end -- 20/04/04: spread out treasure over map more and increased frequency. maze is a good level to buff since it's fun, so we want players to spend more time on it. nerfed treasure in camps to make it less clear whether to attack + if math_random(1, 150) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 250 then entities[#entities + 1] = {name = worm_raffle[math_random(1 + math_floor(game.forces["enemy"].evolution_factor * 8), math_floor(1 + game.forces["enemy"].evolution_factor * 16))], position = p} end end @@ -270,7 +274,7 @@ local function process_hedgemaze_position(p, seed, tiles, entities, treasure, pl end local function process_rocky_position(p, seed, tiles, entities, treasure, planet) - local biters = planet[1].name.biters + local biters = planet[1].type.biters local noise_large_caves = get_noise("large_caves", p, seed) local noise_cave_ponds = get_noise("cave_ponds", p, seed) local small_caves = get_noise("small_caves", p, seed) @@ -292,7 +296,7 @@ local function process_rocky_position(p, seed, tiles, entities, treasure, planet if math_abs(noise_large_caves) > 0.375 then tiles[#tiles + 1] = {name = "dirt-7", position = p} if math_random(1,5) > 1 then entities[#entities + 1] = {name = rock_raffle[math_random(1, size_of_rock_raffle)], position = p} end - if math_random(1,2048) == 1 then treasure[#treasure + 1] = p end + if math_random(1, 2 * 1024) == 1 then treasure[#treasure + 1] = p end return end @@ -331,7 +335,7 @@ local function process_rocky_position(p, seed, tiles, entities, treasure, planet return end - if math_random(1,2048) == 1 then treasure[#treasure + 1] = p end + if math_random(1, 2 * 1024) == 1 then treasure[#treasure + 1] = p end tiles[#tiles + 1] = {name = "dirt-7", position = p} if math_random(1,100) > 50 then entities[#entities + 1] = {name = rock_raffle[math_random(1, size_of_rock_raffle)], position = p} end return @@ -341,7 +345,7 @@ local function process_rocky_position(p, seed, tiles, entities, treasure, planet end local function process_forest_position(p, seed, tiles, entities, treasure, planet) - local biters = planet[1].name.biters + local biters = planet[1].type.biters local noise_forest_location = get_noise("forest_location", p, seed) if noise_forest_location > 0.095 then if noise_forest_location > 0.6 then @@ -368,7 +372,7 @@ end local function process_river_position(p, seed, tiles, entities, treasure, planet) local objective = Chrono_table.get_table() - local biters = planet[1].name.biters + local biters = planet[1].type.biters local richness = math_random(50 + 20 * objective.chronojumps, 100 + 20 * objective.chronojumps) * planet[1].ore_richness.factor * 0.5 local iron_size = get_size_of_ore("iron-ore", planet) * 3 local copper_size = get_size_of_ore("copper-ore", planet) * 3 @@ -421,8 +425,10 @@ local function process_river_position(p, seed, tiles, entities, treasure, planet entities[#entities + 1] = {name = "stone", position = p, amount = richness} end if math_random(1,52 - biters) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 200 then entities[#entities + 1] = {name = spawner_raffle[math_random(1, 4)], position = p} end - if math_random(1,2048) == 1 then treasure[#treasure + 1] = p end end + if math_sqrt(p.x * p.x + p.y * p.y) > 175 and cave_rivers > -0.70 and cave_rivers < 0.70 then + if math_random(1, 4 * 1024) == 1 then treasure[#treasure + 1] = p end + end if noise_forest_location > 0.9 then if math_random(1,100) > 42 then entities[#entities + 1] = {name = tree_raffle[math_random(1, s_tree_raffle)], position = p} end return @@ -438,10 +444,10 @@ local function process_biter_position(p, seed, tiles, entities, treasure, planet local objective = Chrono_table.get_table() local scrapyard = get_noise("scrapyard", p, seed) local large_caves = get_noise("large_caves", p, seed) - local biters = planet[1].name.biters + local biters = planet[1].type.biters local ore_size = planet[1].ore_richness.factor local handicap = 0 - if objective.chronojumps < 5 then handicap = 150 end + if objective.chronojumps < 3 then handicap = 150 end if scrapyard < -0.75 or scrapyard > 0.75 then if math_random(1,52 - biters) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 150 + handicap then entities[#entities + 1] = {name = spawner_raffle[math_random(1, 4)], position = p} end @@ -450,9 +456,9 @@ local function process_biter_position(p, seed, tiles, entities, treasure, planet if scrapyard > -0.05 - 0.01 * ore_size and scrapyard < 0.05 + 0.01 * ore_size then if math_random(1,20) == 1 then entities[#entities + 1] = {name = rock_raffle[math_random(1, size_of_rock_raffle)], position = p} end end - if scrapyard + 0.5 > -0.1 - 0.1 * planet[1].name.moisture and scrapyard + 0.5 < 0.1 + 0.1 * planet[1].name.moisture then + if scrapyard + 0.5 > -0.1 - 0.1 * planet[1].type.moisture and scrapyard + 0.5 < 0.1 + 0.1 * planet[1].type.moisture then local treetypes = tree_raffle[math_random(1, s_tree_raffle)] - if planet[1].name.id == 14 then treetypes = dead_tree_raffle[math_random(1, 5)] end --lava planet + if planet[1].type.id == 14 then treetypes = dead_tree_raffle[math_random(1, 5)] end --lava planet if math_random(1,100) > 42 - handicap / 6 then if math_random(1,800) == 1 then treasure[#treasure + 1] = p @@ -484,7 +490,7 @@ end local function process_scrapyard_position(p, seed, tiles, entities, treasure, planet) local objective = Chrono_table.get_table() local scrapyard = get_noise("scrapyard", p, seed) - local biters = planet[1].name.biters + local biters = planet[1].type.biters --Chasms local noise_cave_ponds = get_noise("cave_ponds", p, seed) local small_caves = get_noise("small_caves", p, seed) @@ -508,7 +514,7 @@ local function process_scrapyard_position(p, seed, tiles, entities, treasure, pl if math_random(1,40) == 1 and math_sqrt(p.x * p.x + p.y * p.y) > 150 then entities[#entities + 1] = {name = spawner_raffle[math_random(1, 4)], position = p} end return end - if scrapyard + 0.5 > -0.05 - 0.1 * planet[1].name.moisture and scrapyard + 0.5 < 0.05 + 0.1 * planet[1].name.moisture then + if scrapyard + 0.5 > -0.05 - 0.1 * planet[1].type.moisture and scrapyard + 0.5 < 0.05 + 0.1 * planet[1].type.moisture then if math_random(1,100) > 42 then entities[#entities + 1] = {name = tree_raffle[math_random(1, s_tree_raffle)], position = p} end end if scrapyard < -0.28 or scrapyard > 0.28 then @@ -542,7 +548,7 @@ end local function process_swamp_position(p, seed, tiles, entities, treasure, planet) local scrapyard = get_noise("scrapyard", p, seed) - local biters = planet[1].name.biters + local biters = planet[1].type.biters if scrapyard < -0.70 or scrapyard > 0.70 then tiles[#tiles + 1] = {name = "grass-3", position = p} @@ -706,7 +712,7 @@ local function get_replacement_tile(surface, position) if not tile.collides_with("resource-layer") then return tile.name end end end - if objective.planet[1].name.id == 18 then return "grass-2" end + if objective.planet[1].type.id == 18 then return "grass-2" end return "grass-1" end @@ -783,7 +789,7 @@ local function empty_chunk(surface, left_top, level, planet) for y = 0, 31, 1 do for x = 0, 31, 1 do local p = {x = left_top.x + x, y = left_top.y + y} - if planet[1].name.id == 16 then + if planet[1].type.id == 16 then process_level(p, seed, tiles, entities, treasure, planet, true, nil) else process_level(p, seed, tiles, entities, treasure, planet) @@ -792,7 +798,7 @@ local function empty_chunk(surface, left_top, level, planet) end surface.set_tiles(tiles, true) replace_water(surface, left_top) - if planet[1].name.id == 18 and left_top.y > 31 and left_top.x > 31 then + if planet[1].type.id == 18 and left_top.y > 31 and left_top.x > 31 then for x = 1, 5, 1 do for y = 1, 5, 1 do local pos = {x = left_top.x + x, y = left_top.y + y} @@ -870,7 +876,7 @@ local function normal_chunk(surface, left_top, level, planet) local treasure = {} local seed = surface.map_gen_settings.seed local process_level = levels[level] - if planet[1].name.id == 16 then + if planet[1].type.id == 16 then local cell = false local roll = math_random(1,20) local things = nil @@ -940,7 +946,7 @@ local function process_chunk(surface, left_top) if not surface then return end if not surface.valid then return end local planet = objective.planet - if planet[1].name.id == 17 then level_depth = 2176 end + if planet[1].type.id == 17 then level_depth = 2176 end if left_top.x >= level_depth * 0.5 or left_top.y >= level_depth * 0.5 then return end if left_top.x < level_depth * -0.5 or left_top.y < level_depth * -0.5 then return end @@ -953,7 +959,7 @@ local function process_chunk(surface, left_top) -- for _, entity in pairs(surface.find_entities_filtered({area = {{p.x - 3, p.y - 4},{p.x + 3, p.y + 10}}, type = "simple-entity"})) do entity.destroy() end -- end - local id = planet[1].name.id --from chronobubbles + local id = planet[1].type.id --from chronobubbles if id == 10 then --scrapyard if math_abs(left_top.y) <= 31 and math_abs(left_top.x) <= 31 then empty_chunk(surface, left_top, 8, planet) return end if math_abs(left_top.y) > 31 or math_abs(left_top.x) > 31 then normal_chunk(surface, left_top, 8, planet) return end diff --git a/maps/chronosphere/tick_functions.lua b/maps/chronosphere/tick_functions.lua index 7bdcb080..df3b1ff4 100644 --- a/maps/chronosphere/tick_functions.lua +++ b/maps/chronosphere/tick_functions.lua @@ -1,4 +1,5 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' local Difficulty = require 'modules.difficulty_vote' local Public_tick = {} @@ -6,342 +7,277 @@ local math_random = math.random local math_floor = math.floor local math_ceil = math.ceil local math_min = math.min +local math_cos = math.cos +local math_sin = math.sin +local math_rad = math.rad +local math_exp = math.exp -function Public_tick.check_chronoprogress() - local objective = Chrono_table.get_table() - if objective.planet[1].name.id == 19 then - if objective.passivetimer == 10 then - game.print({'chronosphere.message_danger1'}, {r = 0.98, g = 0.66, b = 0.22}) - game.print({'chronosphere.message_danger2'}, {r = 0.98, g = 0.66, b = 0.22}) - elseif objective.passivetimer == 25 then - game.print({'chronosphere.message_danger3'}, {r = 0.98, g = 0, b = 0}) - elseif objective.passivetimer == 30 then - game.print({'chronosphere.message_danger4'}, {r = 0.98, g = 0, b = 0}) - end - end - if objective.chronotimer == objective.chrononeeds - 180 then - game.print({'chronosphere.message_jump180'}, {r = 0.98, g = 0.66, b = 0.22}) - elseif objective.chronotimer == objective.chrononeeds - 60 then - game.print({'chronosphere.message_jump60'}, {r = 0.98, g = 0.66, b = 0.22}) - elseif objective.chronotimer == objective.chrononeeds - 30 then - game.print({'chronosphere.message_jump30'}, {r = 0.98, g = 0.66, b = 0.22}) - elseif objective.chronotimer >= objective.chrononeeds - 10 and objective.chrononeeds - objective.chronotimer > 0 then - game.print( - 'Comfylatron: Jump in ' .. objective.chrononeeds - objective.chronotimer .. ' seconds!', - {r = 0.98, g = 0.66, b = 0.22} - ) - end - if objective.chronotimer >= objective.chrononeeds then - return true - end - return false -end +function Public_tick.realtime_events() + local objective = Chrono_table.get_table() -function Public_tick.charge_chronosphere() - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - if not objective.acumulators then - return + -- debug testing for natural jumps (e.g. for misfires): + --if objective.passivetimer == 5 then + -- objective.chronocharges = objective.chronochargesneeded - 10 + --end + + if objective.planet[1].type.id == 19 then + if objective.passivetimer == 3 then + game.print({"chronosphere.message_danger1"}, {r=0.98, g=0.66, b=0.22}) + elseif objective.passivetimer == 15 then + game.print({"chronosphere.message_danger2"}, {r=0.98, g=0.66, b=0.22}) + elseif objective.passivetimer == 25 then + game.print({"chronosphere.message_danger3"}, {r=0.98, g=0, b=0}) + elseif objective.passivetimer == 30 then + game.print({"chronosphere.message_danger4"}, {r=0.98, g=0.66, b=0.22}) + elseif objective.passivetimer == 35 then + game.print({"chronosphere.message_danger5"}, {r=0.98, g=0, b=0}) end - if not objective.chronotimer then - return - end - if objective.chronotimer < 20 then - return - end - if objective.planet[1].name.id == 17 or objective.planet[1].name.id == 19 then - return - end - local acus = objective.acumulators - if #acus < 1 then - return - end - for i = 1, #acus, 1 do - if not acus[i].valid then - return - end - local energy = acus[i].energy - if energy > 3010000 and objective.chronotimer < objective.chrononeeds - 182 and objective.chronotimer > 130 then - acus[i].energy = acus[i].energy - 3000000 - objective.chronotimer = objective.chronotimer + 1 - game.surfaces[objective.active_surface_index].pollute( - objective.locomotive.position, - (10 + 2 * objective.chronojumps) * (3 / (objective.upgrades[2] / 3 + 1)) * Diff.difficulty_vote_value - ) - end + end + + if objective.jump_countdown_start_time == -1 and objective.passivetimer == math_floor(objective.chronochargesneeded * 0.50 / objective.passive_chronocharge_rate) and objective.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) then + game.print({"chronosphere.message_rampup50"}, {r=0.98, g=0.66, b=0.22}) + end + + if objective.jump_countdown_start_time ~= -1 then + if objective.passivetimer == objective.jump_countdown_start_time + objective.jump_countdown_length - 60 then + game.print({"chronosphere.message_jump60"}, {r=0.98, g=0.66, b=0.22}) + elseif objective.passivetimer == objective.jump_countdown_start_time + objective.jump_countdown_length - 30 then + game.print({"chronosphere.message_jump30"}, {r=0.98, g=0.66, b=0.22}) + elseif objective.passivetimer >= objective.jump_countdown_start_time + objective.jump_countdown_length - 10 and objective.jump_countdown_start_time + objective.jump_countdown_length - objective.passivetimer > 0 then + game.print({"chronosphere.message_jump_10orless", objective.jump_countdown_start_time + objective.jump_countdown_length - objective.passivetimer}, {r=0.98, g=0.66, b=0.22}) end + end end function Public_tick.transfer_pollution() - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - local surface = game.surfaces['cargo_wagon'] - if not surface then - return - end - local pollution = surface.get_total_pollution() * (3 / (objective.upgrades[2] / 3 + 1)) * Diff.difficulty_vote_value - game.surfaces[objective.active_surface_index].pollute(objective.locomotive.position, pollution) - surface.clear_pollution() + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + local surface = game.surfaces["cargo_wagon"] + if not surface or not objective.locomotive.valid then return end + + local total_interior_pollution = surface.get_total_pollution() + + local exterior_pollution = total_interior_pollution * Balance.machine_pollution_transfer_from_inside_factor(difficulty, objective.upgrades[2]) + + game.surfaces[objective.active_surface_index].pollute(objective.locomotive.position, exterior_pollution) + -- ascribe the difference to the locomotive: + game.pollution_statistics.on_flow("locomotive", exterior_pollution - total_interior_pollution) + surface.clear_pollution() end -function Public_tick.boost_evolution() - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - if objective.passivetimer > objective.chrononeeds * 0.50 and objective.chronojumps > 5 then - local evolution = game.forces.enemy.evolution_factor - evolution = evolution + (evolution / 500) * Diff.difficulty_vote_value - if evolution > 1 then - evolution = 1 - end - game.forces.enemy.evolution_factor = evolution - end +function Public_tick.ramp_evolution() + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + + if objective.passivetimer * objective.passive_chronocharge_rate > objective.chronochargesneeded * 0.50 and objective.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) then + local evolution = game.forces.enemy.evolution_factor + evolution = evolution * Balance.evoramp50_multiplier_per_10s(difficulty) + if evolution > 1 then evolution = 1 end + game.forces.enemy.evolution_factor = evolution + end end function Public_tick.move_items() - local objective = Chrono_table.get_table() - if not objective.comfychests then - return - end - if not objective.comfychests2 then - return - end - if objective.game_lost == true then - return - end - local input = objective.comfychests - local output = objective.comfychests2 - for i = 1, 24, 1 do - if not input[i].valid then - return - end - if not output[i].valid then - return - end + local objective = Chrono_table.get_table() + if not objective.comfychests then return end + if not objective.comfychests2 then return end + if objective.game_lost == true then return end + local input = objective.comfychests + local output = objective.comfychests2 + for i = 1, 24, 1 do + if not input[i].valid then return end + if not output[i].valid then return end - local input_inventory = input[i].get_inventory(defines.inventory.chest) - local output_inventory = output[i].get_inventory(defines.inventory.chest) - input_inventory.sort_and_merge() - output_inventory.sort_and_merge() - for ii = 1, #input_inventory, 1 do - if input_inventory[ii].valid_for_read then - local count = output_inventory.insert(input_inventory[ii]) - input_inventory[ii].count = input_inventory[ii].count - count - end - end - end + local input_inventory = input[i].get_inventory(defines.inventory.chest) + local output_inventory = output[i].get_inventory(defines.inventory.chest) + input_inventory.sort_and_merge() + output_inventory.sort_and_merge() + for ii = 1, #input_inventory, 1 do + if input_inventory[ii].valid_for_read then + local count = output_inventory.insert(input_inventory[ii]) + input_inventory[ii].count = input_inventory[ii].count - count + end + end + end end function Public_tick.output_items() - local objective = Chrono_table.get_table() - if objective.game_lost == true then - return - end - if not objective.outchests then - return - end - if not objective.locomotive_cargo[2] then - return - end - if not objective.locomotive_cargo[3] then - return - end - if objective.upgrades[8] ~= 1 then - return - end - local wagon = { - [1] = objective.locomotive_cargo[2].get_inventory(defines.inventory.cargo_wagon), - [2] = objective.locomotive_cargo[3].get_inventory(defines.inventory.cargo_wagon) - } - for i = 1, 4, 1 do - if not objective.outchests[i].valid then - return - end - local inv = objective.outchests[i].get_inventory(defines.inventory.chest) - inv.sort_and_merge() - for ii = 1, #inv, 1 do - if inv[ii].valid_for_read then - local count = wagon[math_ceil(i / 2)].insert(inv[ii]) - inv[ii].count = inv[ii].count - count - end - end - end + local objective = Chrono_table.get_table() + if objective.game_lost == true then return end + if not objective.outchests then return end + if not objective.locomotive_cargo[2] then return end + if not objective.locomotive_cargo[3] then return end + if objective.upgrades[8] ~= 1 then return end + local wagon = { + [1] = objective.locomotive_cargo[2].get_inventory(defines.inventory.cargo_wagon), + [2] = objective.locomotive_cargo[3].get_inventory(defines.inventory.cargo_wagon) + } + for i = 1, 4, 1 do + if not objective.outchests[i].valid then return end + local inv = objective.outchests[i].get_inventory(defines.inventory.chest) + inv.sort_and_merge() + for ii = 1, #inv, 1 do + if inv[ii].valid_for_read then + local count = wagon[math_ceil(i/2)].insert(inv[ii]) + inv[ii].count = inv[ii].count - count + end + end + end end function Public_tick.repair_train() - local objective = Chrono_table.get_table() - if not game.surfaces['cargo_wagon'] then - return 0 - end - if objective.game_lost == true then - return 0 - end - local count = 0 - local inv = objective.upgradechest[0].get_inventory(defines.inventory.chest) - if objective.health < objective.max_health then - count = inv.get_item_count('repair-pack') - count = math_min(count, objective.upgrades[6] + 1, math_ceil((objective.max_health - objective.health) / 150)) - if count > 0 then - inv.remove({name = 'repair-pack', count = count}) - end - end - return count * -150 + local objective = Chrono_table.get_table() + if not game.surfaces["cargo_wagon"] then return 0 end + if objective.game_lost == true then return 0 end + local count = 0 + local inv = objective.upgradechest[0].get_inventory(defines.inventory.chest) + if objective.health < objective.max_health then + count = inv.get_item_count("repair-pack") + count = math_min(count, objective.upgrades[6] + 1, math_ceil((objective.max_health - objective.health) / Balance.Chronotrain_HP_repaired_per_pack)) + if count > 0 then inv.remove({name = "repair-pack", count = count}) end + end + return count * -Balance.Chronotrain_HP_repaired_per_pack +end + +local function create_poison_cloud(position) + local objective = Chrono_table.get_table() + local surface = game.surfaces[objective.active_surface_index] + + local tile = surface.get_tile(position.x, position.y) + if not tile then return end + if not tile.valid then return end + if tile.name == "water-shallow" or tile.name == "water-mud" then + local random_angles = {math_rad(math_random(359)),math_rad(math_random(359)),math_rad(math_random(359)),math_rad(math_random(359))} + + surface.create_entity({name = "poison-cloud", position = {x = position.x, y = position.y}}) + surface.create_entity({name = "poison-cloud", position = {x = position.x + 12 * math_cos(random_angles[1]), y = position.y + 12 * math_sin(random_angles[1])}}) + surface.create_entity({name = "poison-cloud", position = {x = position.x + 12 * math_cos(random_angles[2]), y = position.y + 12 * math_sin(random_angles[2])}}) + surface.create_entity({name = "poison-cloud", position = {x = position.x + 12 * math_cos(random_angles[3]), y = position.y + 12 * math_sin(random_angles[3])}}) + surface.create_entity({name = "poison-cloud", position = {x = position.x + 12 * math_cos(random_angles[4]), y = position.y + 12 * math_sin(random_angles[4])}}) + end end function Public_tick.spawn_poison() - local objective = Chrono_table.get_table() - local surface = game.surfaces[objective.active_surface_index] - local random_x = math_random(-460, 460) - local random_y = math_random(-460, 460) - local tile = surface.get_tile(random_x, random_y) - if not tile.valid then - return - end - if tile.name == 'water-shallow' or tile.name == 'water-mud' then - surface.create_entity({name = 'poison-cloud', position = {x = random_x, y = random_y}}) - surface.create_entity({name = 'poison-cloud', position = {x = random_x + 2, y = random_y + 2}}) - surface.create_entity({name = 'poison-cloud', position = {x = random_x - 2, y = random_y - 2}}) - surface.create_entity({name = 'poison-cloud', position = {x = random_x + 2, y = random_y - 2}}) - surface.create_entity({name = 'poison-cloud', position = {x = random_x - 2, y = random_y + 2}}) - end + local random_x = math_random(-460,460) + local random_y = math_random(-460,460) + create_poison_cloud{x = random_x, y = random_y} + if math_random(1,3) == 1 then + local random_angles = {math_rad(math_random(359))} + create_poison_cloud{x = random_x + 24 * math_cos(random_angles[1]), y = random_y + 24 * math_sin(random_angles[1])} + end end local function launch_nukes() - local objective = Chrono_table.get_table() - local surface = game.surfaces[objective.active_surface_index] - if objective.dangers and #objective.dangers > 1 then - for i = 1, #objective.dangers, 1 do - if objective.dangers[i].destroyed == false then - local fake_shooter = - surface.create_entity( - {name = 'character', position = objective.dangers[i].silo.position, force = 'enemy'} - ) - surface.create_entity( - { - name = 'atomic-rocket', - position = objective.dangers[i].silo.position, - force = 'enemy', - speed = 1, - max_range = 800, - target = objective.locomotive, - source = fake_shooter - } - ) - game.print({'chronosphere.message_nuke'}, {r = 0.98, g = 0, b = 0}) - end - end + local objective = Chrono_table.get_table() + local surface = game.surfaces[objective.active_surface_index] + if objective.dangers and #objective.dangers > 1 then + for i = 1, #objective.dangers, 1 do + if objective.dangers[i].destroyed == false then + local fake_shooter = surface.create_entity({name = "character", position = objective.dangers[i].silo.position, force = "enemy"}) + surface.create_entity({name = "atomic-rocket", position = objective.dangers[i].silo.position, force = "enemy", speed = 1, max_range = 800, target = objective.locomotive, source = fake_shooter}) + game.print({"chronosphere.message_nuke"}, {r=0.98, g=0, b=0}) + end end + end end function Public_tick.dangertimer() - local objective = Chrono_table.get_table() - local timer = objective.dangertimer - if timer == 0 then - return - end - if objective.planet[1].name.id == 19 then - timer = timer - 1 - if objective.dangers and #objective.dangers > 0 then - for i = 1, #objective.dangers, 1 do - if objective.dangers[i].destroyed == false then - if timer == 15 then - objective.dangers[i].silo.launch_rocket() - objective.dangers[i].silo.rocket_parts = 100 - end - rendering.set_text( - objective.dangers[i].timer, - math_floor(timer / 60) .. ' min, ' .. timer % 60 .. ' s' - ) - end - end + local objective = Chrono_table.get_table() + local timer = objective.dangertimer + if timer == 0 then return end + if objective.planet[1].type.id == 19 then + timer = timer - 1 + if objective.dangers and #objective.dangers > 0 then + for i = 1, #objective.dangers, 1 do + if objective.dangers[i].destroyed == false then + if timer == 15 then + objective.dangers[i].silo.launch_rocket() + objective.dangers[i].silo.rocket_parts = 100 + end + rendering.set_text(objective.dangers[i].timer, math_floor(timer / 60) .. " min, " .. timer % 60 .. " s") end - else - timer = 1200 - end - if timer < 0 then - timer = 0 - end - if timer == 0 then - launch_nukes() - timer = 90 + end end + else + timer = 1200 + end + if timer < 0 then timer = 0 end + if timer == 0 then + launch_nukes() + timer = 90 + end - objective.dangertimer = timer + objective.dangertimer = timer end function Public_tick.offline_players() - local objective = Chrono_table.get_table() - if objective.chronotimer > objective.chrononeeds - 182 or objective.passivetimer < 30 then - return - end - --local current_tick = game.tick - local players = objective.offline_players - local surface = game.surfaces[objective.active_surface_index] - if #players > 0 then - --log("nonzero offline players") - local later = {} - for i = 1, #players, 1 do - if players[i] and game.players[players[i].index] and game.players[players[i].index].connected then - --game.print("deleting already online character from list") - players[i] = nil - else - if players[i] and players[i].tick < game.tick - 54000 then - --log("spawning corpse") - local player_inv = {} - local items = {} - player_inv[1] = game.players[players[i].index].get_inventory(defines.inventory.character_main) - player_inv[2] = game.players[players[i].index].get_inventory(defines.inventory.character_armor) - player_inv[3] = game.players[players[i].index].get_inventory(defines.inventory.character_guns) - player_inv[4] = game.players[players[i].index].get_inventory(defines.inventory.character_ammo) - player_inv[5] = game.players[players[i].index].get_inventory(defines.inventory.character_trash) - local e = - surface.create_entity( - { - name = 'character', - position = game.forces.player.get_spawn_position(surface), - force = 'neutral' - } - ) - local inv = e.get_inventory(defines.inventory.character_main) - for ii = 1, 5, 1 do - if player_inv[ii].valid then - for iii = 1, #player_inv[ii], 1 do - if player_inv[ii][iii].valid then - items[#items + 1] = player_inv[ii][iii] - end - end - end - end - if #items > 0 then - for item = 1, #items, 1 do - if items[item].valid then - inv.insert(items[item]) - end - end - game.print({'chronosphere.message_accident'}, {r = 0.98, g = 0.66, b = 0.22}) - e.die('neutral') - else - e.destroy() - end - - for ii = 1, 5, 1 do - if player_inv[ii].valid then - player_inv[ii].clear() - end - end - players[i] = nil - else - later[#later + 1] = players[i] + local objective = Chrono_table.get_table() + if objective.chronocharges == objective.chronochargesneeded or objective.passivetimer < 30 then return end + --local current_tick = game.tick + local players = objective.offline_players + local surface = game.surfaces[objective.active_surface_index] + if #players > 0 then + --log("nonzero offline players") + local later = {} + for i = 1, #players, 1 do + if players[i] and game.players[players[i].index] and game.players[players[i].index].connected then + --game.print("deleting already online character from list") + players[i] = nil + else + if players[i] and players[i].tick < game.tick - 54000 then + --log("spawning corpse") + local player_inv = {} + local items = {} + player_inv[1] = game.players[players[i].index].get_inventory(defines.inventory.character_main) + player_inv[2] = game.players[players[i].index].get_inventory(defines.inventory.character_armor) + player_inv[3] = game.players[players[i].index].get_inventory(defines.inventory.character_guns) + player_inv[4] = game.players[players[i].index].get_inventory(defines.inventory.character_ammo) + player_inv[5] = game.players[players[i].index].get_inventory(defines.inventory.character_trash) + local e = surface.create_entity({name = "character", position = game.forces.player.get_spawn_position(surface), force = "neutral"}) + local inv = e.get_inventory(defines.inventory.character_main) + for ii = 1, 5, 1 do + if player_inv[ii].valid then + for iii = 1, #player_inv[ii], 1 do + if player_inv[ii][iii].valid then + items[#items + 1] = player_inv[ii][iii] end + end end - end - players = {} - if #later > 0 then - for i = 1, #later, 1 do - players[#players + 1] = later[i] + end + if #items > 0 then + for item = 1, #items, 1 do + if items[item].valid then + inv.insert(items[item]) + end end + game.print({"chronosphere.message_accident"}, {r=0.98, g=0.66, b=0.22}) + e.die("neutral") + -- thesixthroc: do we also want to mark the player as offline for purposes of 'time played?' + else + e.destroy() + end + + for ii = 1, 5, 1 do + if player_inv[ii].valid then + player_inv[ii].clear() + end + end + players[i] = nil + else + later[#later + 1] = players[i] end - objective.offline_players = players + end end + players = {} + if #later > 0 then + for i = 1, #later, 1 do + players[#players + 1] = later[i] + end + end + objective.offline_players = players + end end + return Public_tick diff --git a/maps/chronosphere/treasure.lua b/maps/chronosphere/treasure.lua index 877f8fad..a6f4c528 100644 --- a/maps/chronosphere/treasure.lua +++ b/maps/chronosphere/treasure.lua @@ -1,179 +1,306 @@ local Chrono_table = require 'maps.chronosphere.table' +local Rand = require 'maps.chronosphere.random' +local Balance = require 'maps.chronosphere.balance' +local Difficulty = require 'modules.difficulty_vote' local math_random = math.random +local math_abs = math.abs +local math_max = math.max +local math_min = math.min +local math_ceil = math.ceil local Public = {} + +local function treasure_chest_loot(difficulty, planet) + + local function loot_data_sensible(loot_data_item) + return {weight = loot_data_item[1], d_min = loot_data_item[2], d_max = loot_data_item[3], scaling = loot_data_item[4], name = loot_data_item[5], min_count = loot_data_item[6], max_count = loot_data_item[7]} + end + + local loot_data_raw= { + --always there (or normally always there): + + {8, 0, 1, false, "railgun-dart", 8, 16}, -- thesixthroc: this should not scale with jumps. reward treasure hunting currency the same at all jump numbers + {8, 0, 1, false, "coin", 4, 60}, + + {4, 0, 1, false, "pistol", 1, 2}, + {1, 0, 1, false, "gun-turret", 2, 4}, + {6, 0, 1, false, "grenade", 2, 21}, + {4, 0, 1, false, "stone-wall", 24, 100}, + {4, 0, 1, false, "gate", 14, 32}, + {1, 0, 1, false, "radar", 1, 2}, + {1, 0, 1, false, "explosives", 10, 50}, + {6, 0, 1, false, "small-lamp", 8, 32}, + {2, 0, 1, false, "electric-mining-drill", 2, 4}, + {3, 0, 1, false, "long-handed-inserter", 4, 16}, + {0.5, 0, 1, false, "filter-inserter", 2, 12}, + {0.2, 0, 1, false, "stack-filter-inserter", 2, 6}, + {0.2, 0, 1, false, "slowdown-capsule", 2, 4}, + {0.2, 0, 1, false, "destroyer-capsule", 2, 4}, + {0.2, 0, 1, false, "defender-capsule", 2, 4}, + {0.2, 0, 1, false, "distractor-capsule", 2, 4}, + {0.25, 0, 1, false, "rail", 50, 100}, + {0.25, 0, 1, false, "uranium-rounds-magazine", 1, 4}, + {1, 0.15, 1, false, "pump", 1, 2}, + {2, 0.15, 1, false, "pumpjack", 1, 3}, + {0.02, 0.15, 1, false, "oil-refinery", 1, 2}, + + --shotgun meta: + {10, -0.2, 0.4, true, "shotgun-shell", 12, 24}, + {5, 0, 0.4, true, "shotgun", 1, 1}, + {3, 0, 1.2, true, "piercing-shotgun-shell", 8, 24}, + {2, 0, 1.2, true, "combat-shotgun", 1, 1}, + + --modular armor meta: + {0.7, -3, 1, true, "modular-armor", 1, 1}, + {0.4, 0.3, 1, true, "power-armor", 1, 1}, + -- {0.5, -1,3, true, "power-armor-mk2", 1, 1}, + {2, 0, 1, true, "solar-panel-equipment", 1, 2}, + {2, 0, 1, true, "battery-equipment", 1, 1}, + {1.6, 0, 1, true, "energy-shield-equipment", 1, 2}, + {0.8, 0, 1, true, "night-vision-equipment", 1, 1}, + {0.4, 0.5, 1.5, true, "personal-laser-defense-equipment", 1, 1}, + + --loader meta: + {math_max(1.5 * difficulty - 1.25, 0), 0, 0.2, false, "loader", 1, 2}, + {math_max(1.5 * difficulty - 1.25, 0), 0.2, 0.6, false, "fast-loader", 1, 2}, + {math_max(1.5 * difficulty - 1.25, 0), 0.6, 1, false, "express-loader", 1, 2}, + + --science meta: + {8, -0.5, 0.5, true, "automation-science-pack", 4, 12}, + {8, -0.6, 0.6, true, "logistic-science-pack", 4, 12}, + {6, -0.1, 1, true, "military-science-pack", 8, 8}, --careful with this + {6, 0.2, 1.4, true, "chemical-science-pack", 16, 24}, + {6, 0.3, 1.5, true, "production-science-pack", 16, 24}, + {4, 0.4, 1.5, true, "utility-science-pack", 16, 24}, + {10, 0.5, 1.5, true, "space-science-pack", 16, 24}, + + --early-game: + {3, -0.1, 0.1, true, "wooden-chest", 8, 40}, + {5, -0.1, 0.1, true, "burner-inserter", 8, 20}, + {1, -0.2, 0.2, true, "offshore-pump", 1, 3}, + {3, -0.2, 0.2, true, "boiler", 3, 6}, + {6, -0.2, 0.2, true, "lab", 1, 2}, + {3, -0.2, 0.2, true, "steam-engine", 2, 4}, + {3, -0.2, 0.2, true, "burner-mining-drill", 2, 4}, + {2.7, 0, 0.15, false, "submachine-gun", 1, 3}, + {0.3, 0, 0.15, false, "vehicle-machine-gun", 1, 1}, + {3, 0, 0.3, true, "iron-chest", 8, 40}, + {4, -0.3, 0.3, true, "light-armor", 1, 1}, + {4, -0.3, 0.3, true, "inserter", 8, 16}, + {8, -0.3, 0.3, true, "small-electric-pole", 16, 32}, + {6, -0.4, 0.4, true, "stone-furnace", 8, 16}, + {8, -0.5, 0.5, true, "firearm-magazine", 32, 128}, + {1, -0.3, 0.3, true, "underground-belt", 3, 10}, + {1, -0.3, 0.3, true, "splitter", 1, 5}, + {1, -0.3, 0.3, true, "assembling-machine-1", 2, 4}, + {5, -0.8, 0.8, true, "transport-belt", 15, 120}, + + --mid-game: + {5, -0.2, 0.7, true, "pipe", 30, 50}, + {1, -0.2, 0.7, true, "pipe-to-ground", 4, 8}, + {5, -0.2, 0.7, true, "iron-gear-wheel", 40, 160}, + {5, -0.2, 0.7, true, "copper-cable", 60, 200}, + {5, -0.2, 0.7, true, "electronic-circuit", 30, 200}, + {4, -0.1, 0.8, true, "fast-transport-belt", 15, 90}, + {4, -0.1, 0.8, true, "fast-underground-belt", 3, 10}, + {4, -0.1, 0.8, true, "fast-splitter", 1, 5}, + {2, 0, 0.6, true, "storage-tank", 2, 6}, + {4, 0, 0.6, true, "heavy-armor", 1, 1}, + {3, 0, 0.7, true, "steel-plate", 15, 100}, + {8, 0, 0.9, true, "piercing-rounds-magazine", 20, 128}, + {4, 0.2, 0.6, true, "engine-unit", 16, 32}, + {4, 0, 1, true, "fast-inserter", 8, 16}, + {5, 0, 1, true, "steel-furnace", 4, 8}, + {5, 0, 1, true, "assembling-machine-2", 2, 4}, + {5, 0, 1, true, "medium-electric-pole", 6, 20}, + {5, 0, 1, true, "accumulator", 4, 8}, + {5, 0, 1, true, "solar-panel", 3, 6}, + {8, 0, 1, true, "steel-chest", 8, 16}, + {3, 0.2, 1, true, "chemical-plant", 1, 3}, + + --late-game: + {3, 0, 1.2, true, "rocket-launcher", 1, 1}, + {5, 0, 1.2, true, "rocket", 16, 32}, + {3, 0, 1.2, true, "land-mine", 16, 32}, + {4, 0.2, 1.2, true, "lubricant-barrel", 4, 10}, + {1, 0.2, 1.2, true, "battery", 50, 150}, + {5, 0.2, 1.8, true, "explosive-rocket", 16, 32}, + {4, 0.2, 1.4, true, "advanced-circuit", 30, 200}, + {3, 0.2, 1.8, true, "stack-inserter", 4, 8}, + {3, 0.2, 1.4, true, "big-electric-pole", 4, 8}, + {2, 0.3, 1, true, "rocket-fuel", 4, 10}, + {5, 0.4, 0.7, true, "cannon-shell", 16, 32}, + {5, 0.4, 0.8, true, "explosive-cannon-shell", 16, 32}, + {2, 0.4, 1, true, "electric-engine-unit", 16, 32}, + {5, 0.2, 1.8, true, "cluster-grenade", 8, 16}, + {5, 0.2, 1.4, true, "construction-robot", 5, 25}, + {2, 0.25, 1.75, true, "logistic-robot", 5, 25}, + {2, 0.25, 1.75, true, "substation", 2, 4}, + {3, 0.25, 1.75, true, "assembling-machine-3", 2, 4}, + {3, 0.25, 1.75, true, "express-transport-belt", 15, 90}, + {3, 0.25, 1.75, true, "express-underground-belt", 3, 10}, + {3, 0.25, 1.75, true, "express-splitter", 1, 5}, + {3, 0.25, 1.75, true, "electric-furnace", 2, 4}, + {3, 0.25, 1.75, true, "laser-turret", 3, 6}, + {4, 0.4, 1.6, true, "processing-unit", 30, 200}, + {2, 0.6, 1.4, true, "roboport", 1, 1}, + + -- super late-game: + {1, 0.9, 1.1, true, "power-armor-mk2", 1, 1}, + + --{2, 0, 1, , "computer", 1, 1}, + --{1, 0.2, 1, , "railgun", 1, 1}, + --{1, 0.9, 1, , "personal-roboport-mk2-equipment", 1, 1}, + } + local specialised_loot_raw = {} + + if planet.type.id == 3 then --stonewrld + specialised_loot_raw = { + {20, 0, 1, false, "stone-brick", 10, 300}, + {25, 0, 1, false, "stone-wall", 20, 100}, + {25, 0, 1, false, "refined-hazard-concrete", 50, 200} + } + end + + if planet.type.id == 5 then --uraniumwrld + specialised_loot_raw = { + {3, 0, 0.8, true, "steam-turbine", 1, 2}, + {3, 0, 0.8, true, "heat-exchanger", 2, 4}, + {3, 0, 0.8, true, "heat-pipe", 4, 8}, + {2, 0, 2, true, "uranium-rounds-magazine", 6, 48}, + {2, 0, 1, true, "uranium-cannon-shell", 12, 32}, + {4, 0.4, 1.6, true, "explosive-uranium-cannon-shell", 12, 32}, + {10, 0, 1, false, "uranium-238", 8, 32}, + {0.1, 0, 1, false, "uranium-235", 2, 12}, + {2, 0.2, 1, false, "nuclear-reactor", 1, 1}, + {2, 0.2, 1, false, "centrifuge", 1, 1}, + {1, 0.25, 1, false, "nuclear-fuel", 1, 1}, + {1, 0.25, 1, false, "fusion-reactor-equipment", 1, 1}, + {1, 0.5, 1, false, "atomic-bomb", 1, 1}, + } + end + + --[[ + if planet.type.id == 7 then --biterwrld + specialised_loot_raw = { + {4, 0, 1, false, "effectivity-module", 1, 4}, + {4, 0, 1, false, "productivity-module", 1, 4}, + {4, 0, 1, false, "speed-module", 1, 4}, + {2, 0, 1, false, "beacon", 1, 1}, + {0.5, 0, 1, false, "effectivity-module-2", 1, 4}, + {0.5, 0, 1, false, "productivity-module-2", 1, 4}, + {0.5, 0, 1, false, "speed-module-2", 1, 4}, + {0.1, 0, 1, false, "effectivity-module-3", 1, 4}, + {0.1, 0, 1, false, "productivity-module-3", 1, 4}, + {0.1, 0, 1, false, "speed-module-3", 1, 4}, + + } + end + ]] + + if planet.type.id == 14 then --ancient battlefield + specialised_loot_raw = { + {5, -0.7, 0.7, true, "light-armor", 1, 1}, + {5, -0.3, 0.9, true, "heavy-armor", 1, 1}, + {5, 0.4, 0.7, true, "cannon-shell", 16, 32}, + {8, -0.7, 0.7, true, "firearm-magazine", 32, 128}, + {4, -0.2, 1.2, true, "piercing-rounds-magazine", 32, 128}, + {3, 0.2, 1.8, true, "uranium-rounds-magazine", 32, 128}, + {3, 0, 2, true, "rocket-launcher", 1, 1}, + {1, -1, 3, true, "flamethrower", 1, 1}, + {1, -1, 3, true, "flamethrower-ammo", 16, 32}, + } + end + + if planet.type.id == 14 then --lavawrld + specialised_loot_raw = { + {6, -1, 3, true, "flamethrower-turret", 1, 1}, + {7, -1, 2, true, "flamethrower", 1, 1}, + {14, -1, 2, true, "flamethrower-ammo", 16, 32}, + } + end + + if planet.type.id == 16 then --mazewrld + specialised_loot_raw = { + {2, 0, 1, false, "programmable-speaker", 2, 4}, + {6, 0, 1, false, "arithmetic-combinator", 4, 8}, + {6, 0, 1, false, "constant-combinator", 4, 8}, + {6, 0, 1, false, "decider-combinator", 4, 8}, + {6, 0, 1, false, "power-switch", 1, 1}, + {9, 0, 1, false, "green-wire", 10, 29}, + {9, 0, 1, false, "red-wire", 10, 29}, + + {11, 0, 0.6, true, "modular-armor", 1, 1}, + {7, -0.2,1, true, "power-armor", 1, 1}, + {3, 0,2, true, "power-armor-mk2", 1, 1}, + + {4, 0, 1, false, "exoskeleton-equipment", 1, 1}, + {4, 0, 1, false, "belt-immunity-equipment", 1, 1}, + {4, 0, 1, true, "energy-shield-equipment", 1, 2}, + {4, 0, 1, false, "night-vision-equipment", 1, 1}, + {4, 0, 1, false, "discharge-defense-equipment", 1, 1}, + {4, 0.2, 1, false, "personal-roboport-equipment", 1, 2}, + {4, 0.4, 1, false, "personal-laser-defense-equipment", 1, 1}, + {8, 0, 1, false, "solar-panel-equipment", 1, 2}, + {8, 0, 1, false, "battery-equipment", 1, 1}, + + {1, 0.5, 1, false, "energy-shield-mk2-equipment", 1, 1}, + {1, 0.5, 1, false, "battery-mk2-equipment", 1, 1}, + + {3, 0, 1, true, "copper-cable", 20, 400}, + {3, -0.3, 0.6, true, "electronic-circuit", 50, 100}, + {3, 0.2, 1.4, true, "advanced-circuit", 50, 100}, + {3, 0.5, 1.5, true, "processing-unit", 50, 100}, + } + end + + if planet.type.id == 18 then --swampwrld + specialised_loot_raw = { + {25, 0, 1, false, "poison-capsule", 4, 16}, + {45, 0, 1, false, "sulfuric-acid-barrel", 4, 8}, + } + end + + local loot_data = {} + for l=1,#loot_data_raw,1 do + table.insert(loot_data, loot_data_sensible(loot_data_raw[l])) + end + for l=1,#specialised_loot_raw,1 do + table.insert(loot_data, loot_data_sensible(specialised_loot_raw[l])) + end + + return loot_data +end + function Public.treasure_chest(surface, position, container_name) local objective = Chrono_table.get_table() + local jumps = 0 + if objective.chronojumps then jumps = objective.chronojumps end + local difficulty = 1 + if Difficulty.get().difficulty_vote_value then difficulty = Difficulty.get().difficulty_vote_value end + if jumps == 0 then difficulty = 1 end --Always treat the first level as normal difficulty + local chest_raffle = {} - local chest_loot = { - {{name = "submachine-gun", count = math_random(1,3)}, weight = 3, d_min = 0.0, d_max = 0.1}, - {{name = "pistol", count = math_random(1,2)}, weight = 1, d_min = 0.0, d_max = 1}, - {{name = "slowdown-capsule", count = math_random(16,32)}, weight = 1, d_min = 0.3, d_max = 0.7}, - {{name = "poison-capsule", count = math_random(8,16)}, weight = 3, d_min = 0.3, d_max = 1}, - {{name = "uranium-cannon-shell", count = math_random(16,32)}, weight = 5, d_min = 0.6, d_max = 1}, - {{name = "cannon-shell", count = math_random(16,32)}, weight = 5, d_min = 0.4, d_max = 0.7}, - {{name = "explosive-uranium-cannon-shell", count = math_random(16,32)}, weight = 5, d_min = 0.6, d_max = 1}, - {{name = "explosive-cannon-shell", count = math_random(16,32)}, weight = 5, d_min = 0.4, d_max = 0.8}, - {{name = "shotgun", count = 1}, weight = 2, d_min = 0.0, d_max = 0.2}, - {{name = "shotgun-shell", count = math_random(16,32)}, weight = 5, d_min = 0.0, d_max = 0.2}, - {{name = "combat-shotgun", count = 1}, weight = 3, d_min = 0.3, d_max = 0.8}, - {{name = "piercing-shotgun-shell", count = math_random(16,32)}, weight = 10, d_min = 0.2, d_max = 1}, - {{name = "flamethrower", count = 1}, weight = 3, d_min = 0.3, d_max = 0.6}, - {{name = "flamethrower-ammo", count = math_random(16,32)}, weight = 5, d_min = 0.3, d_max = 1}, - {{name = "rocket-launcher", count = 1}, weight = 3, d_min = 0.2, d_max = 0.6}, - {{name = "rocket", count = math_random(16,32)}, weight = 5, d_min = 0.2, d_max = 0.7}, - {{name = "explosive-rocket", count = math_random(16,32)}, weight = 5, d_min = 0.3, d_max = 1}, - {{name = "land-mine", count = math_random(16,32)}, weight = 5, d_min = 0.2, d_max = 0.7}, - {{name = "grenade", count = math_random(16,32)}, weight = 5, d_min = 0.0, d_max = 0.5}, - {{name = "cluster-grenade", count = math_random(8,16)}, weight = 5, d_min = 0.4, d_max = 1}, - {{name = "firearm-magazine", count = math_random(32,128)}, weight = 5, d_min = 0, d_max = 0.3}, - {{name = "piercing-rounds-magazine", count = math_random(32,128)}, weight = 5, d_min = 0.1, d_max = 0.8}, - {{name = "uranium-rounds-magazine", count = math_random(32,128)}, weight = 5, d_min = 0.5, d_max = 1}, - --{{name = "railgun", count = 1}, weight = 1, d_min = 0.2, d_max = 1}, - {{name = "railgun-dart", count = math_random(2,4)}, weight = 4, d_min = 0, d_max = 0.2}, - {{name = "railgun-dart", count = math_random(4,8)}, weight = 4, d_min = 0.1, d_max = 0.4}, - {{name = "railgun-dart", count = math_random(8,12)}, weight = 4, d_min = 0.3, d_max = 0.6}, - {{name = "railgun-dart", count = math_random(12,16)}, weight = 4, d_min = 0.5, d_max = 0.8}, - {{name = "railgun-dart", count = math_random(16,20)}, weight = 4, d_min = 0.7, d_max = 1}, - {{name = "defender-capsule", count = math_random(8,16)}, weight = 2, d_min = 0.0, d_max = 0.7}, - {{name = "distractor-capsule", count = math_random(8,16)}, weight = 2, d_min = 0.2, d_max = 1}, - {{name = "destroyer-capsule", count = math_random(8,16)}, weight = 2, d_min = 0.3, d_max = 1}, - {{name = "atomic-bomb", count = 1}, weight = 1, d_min = 0.8, d_max = 1}, - {{name = "light-armor", count = 1}, weight = 3, d_min = 0, d_max = 0.05}, - {{name = "heavy-armor", count = 1}, weight = 3, d_min = 0.05, d_max = 0.25}, - {{name = "modular-armor", count = 1}, weight = 2, d_min = 0.25, d_max = 0.5}, - {{name = "power-armor", count = 1}, weight = 1, d_min = 0.4, d_max = 1}, - {{name = "power-armor-mk2", count = 1}, weight = 1, d_min = 0.9, d_max = 1}, - {{name = "battery-equipment", count = 1}, weight = 2, d_min = 0.3, d_max = 0.7}, - --{{name = "battery-mk2-equipment", count = 1}, weight = 2, d_min = 0.7, d_max = 1}, - {{name = "belt-immunity-equipment", count = 1}, weight = 1, d_min = 0.5, d_max = 1}, - {{name = "solar-panel-equipment", count = math_random(1,4)}, weight = 5, d_min = 0.4, d_max = 0.8}, - {{name = "discharge-defense-equipment", count = 1}, weight = 1, d_min = 0.5, d_max = 1}, - {{name = "energy-shield-equipment", count = math_random(1,2)}, weight = 2, d_min = 0.3, d_max = 0.8}, - --{{name = "energy-shield-mk2-equipment", count = 1}, weight = 2, d_min = 0.8, d_max = 1}, - {{name = "exoskeleton-equipment", count = 1}, weight = 1, d_min = 0.3, d_max = 1}, - {{name = "fusion-reactor-equipment", count = 1}, weight = 1, d_min = 0.8, d_max = 1}, - {{name = "night-vision-equipment", count = 1}, weight = 1, d_min = 0.3, d_max = 0.8}, - {{name = "personal-laser-defense-equipment", count = 1}, weight = 1, d_min = 0.7, d_max = 1}, - {{name = "personal-roboport-equipment", count = math_random(1,2)}, weight = 3, d_min = 0.4, d_max = 1}, - --{{name = "personal-roboport-mk2-equipment", count = 1}, weight = 1, d_min = 0.9, d_max = 1}, - {{name = "logistic-robot", count = math_random(5,25)}, weight = 2, d_min = 0.5, d_max = 1}, - {{name = "construction-robot", count = math_random(5,25)}, weight = 5, d_min = 0.4, d_max = 1}, - - {{name = "iron-gear-wheel", count = math_random(80,100)}, weight = 3, d_min = 0.0, d_max = 0.3}, - {{name = "copper-cable", count = math_random(100,200)}, weight = 3, d_min = 0.0, d_max = 0.3}, - {{name = "engine-unit", count = math_random(16,32)}, weight = 2, d_min = 0.1, d_max = 0.5}, - {{name = "electric-engine-unit", count = math_random(16,32)}, weight = 2, d_min = 0.4, d_max = 0.8}, - {{name = "battery", count = math_random(50,150)}, weight = 2, d_min = 0.3, d_max = 0.8}, - {{name = "advanced-circuit", count = math_random(50,150)}, weight = 3, d_min = 0.3, d_max = 1}, - {{name = "electronic-circuit", count = math_random(50,150)}, weight = 4, d_min = 0.0, d_max = 0.4}, - {{name = "processing-unit", count = math_random(50,150)}, weight = 3, d_min = 0.7, d_max = 1}, - {{name = "explosives", count = math_random(20,50)}, weight = 7, d_min = 0.0, d_max = 1}, - {{name = "lubricant-barrel", count = math_random(4,10)}, weight = 1, d_min = 0.3, d_max = 0.5}, - {{name = "rocket-fuel", count = math_random(4,10)}, weight = 2, d_min = 0.3, d_max = 0.7}, - --{{name = "computer", count = 1}, weight = 2, d_min = 0, d_max = 1}, - - {{name = "effectivity-module", count = math_random(1,4)}, weight = 2, d_min = 0.1, d_max = 1}, - {{name = "productivity-module", count = math_random(1,4)}, weight = 2, d_min = 0.1, d_max = 1}, - {{name = "speed-module", count = math_random(1,4)}, weight = 2, d_min = 0.1, d_max = 1}, - - {{name = "automation-science-pack", count = math_random(16,64)}, weight = 4, d_min = 0.0, d_max = 0.2}, - {{name = "logistic-science-pack", count = math_random(16,64)}, weight = 4, d_min = 0.05, d_max = 0.5}, - {{name = "military-science-pack", count = math_random(16,64)}, weight = 4, d_min = 0.15, d_max = 1}, - {{name = "chemical-science-pack", count = math_random(16,64)}, weight = 4, d_min = 0.3, d_max = 1}, - {{name = "production-science-pack", count = math_random(16,64)}, weight = 4, d_min = 0.4, d_max = 1}, - {{name = "utility-science-pack", count = math_random(16,64)}, weight = 4, d_min = 0.5, d_max = 1}, - {{name = "space-science-pack", count = math_random(16,64)}, weight = 4, d_min = 0.9, d_max = 1}, - - {{name = "steel-plate", count = math_random(25,75)}, weight = 2, d_min = 0.1, d_max = 0.3}, - {{name = "nuclear-fuel", count = 1}, weight = 2, d_min = 0.7, d_max = 1}, - - {{name = "burner-inserter", count = math_random(8,16)}, weight = 3, d_min = 0.0, d_max = 0.1}, - {{name = "inserter", count = math_random(8,16)}, weight = 3, d_min = 0.0, d_max = 0.4}, - {{name = "long-handed-inserter", count = math_random(8,16)}, weight = 3, d_min = 0.0, d_max = 0.4}, - {{name = "fast-inserter", count = math_random(8,16)}, weight = 3, d_min = 0.1, d_max = 1}, - {{name = "filter-inserter", count = math_random(8,16)}, weight = 1, d_min = 0.2, d_max = 1}, - {{name = "stack-filter-inserter", count = math_random(4,8)}, weight = 1, d_min = 0.4, d_max = 1}, - {{name = "stack-inserter", count = math_random(4,8)}, weight = 3, d_min = 0.3, d_max = 1}, - {{name = "small-electric-pole", count = math_random(16,24)}, weight = 3, d_min = 0.0, d_max = 0.3}, - {{name = "medium-electric-pole", count = math_random(8,16)}, weight = 3, d_min = 0.2, d_max = 1}, - {{name = "big-electric-pole", count = math_random(4,8)}, weight = 3, d_min = 0.3, d_max = 1}, - {{name = "substation", count = math_random(2,4)}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "wooden-chest", count = math_random(8,16)}, weight = 3, d_min = 0.0, d_max = 0.2}, - {{name = "iron-chest", count = math_random(8,16)}, weight = 3, d_min = 0.1, d_max = 0.4}, - {{name = "steel-chest", count = math_random(8,16)}, weight = 3, d_min = 0.3, d_max = 1}, - {{name = "small-lamp", count = math_random(16,32)}, weight = 3, d_min = 0.1, d_max = 0.3}, - {{name = "rail", count = math_random(25,75)}, weight = 3, d_min = 0.1, d_max = 0.6}, - {{name = "assembling-machine-1", count = math_random(2,4)}, weight = 3, d_min = 0.0, d_max = 0.3}, - {{name = "assembling-machine-2", count = math_random(2,4)}, weight = 3, d_min = 0.2, d_max = 0.8}, - {{name = "assembling-machine-3", count = math_random(2,4)}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "accumulator", count = math_random(4,8)}, weight = 3, d_min = 0.4, d_max = 1}, - {{name = "offshore-pump", count = math_random(1,3)}, weight = 2, d_min = 0.0, d_max = 0.2}, - {{name = "beacon", count = 1}, weight = 2, d_min = 0.7, d_max = 1}, - {{name = "boiler", count = math_random(3,6)}, weight = 3, d_min = 0.0, d_max = 0.3}, - {{name = "steam-engine", count = math_random(2,4)}, weight = 3, d_min = 0.0, d_max = 0.5}, - {{name = "steam-turbine", count = math_random(1,2)}, weight = 2, d_min = 0.6, d_max = 1}, - {{name = "nuclear-reactor", count = 1}, weight = 1, d_min = 0.7, d_max = 1}, - {{name = "centrifuge", count = 1}, weight = 1, d_min = 0.6, d_max = 1}, - {{name = "heat-pipe", count = math_random(4,8)}, weight = 2, d_min = 0.5, d_max = 1}, - {{name = "heat-exchanger", count = math_random(2,4)}, weight = 2, d_min = 0.5, d_max = 1}, - {{name = "arithmetic-combinator", count = math_random(4,8)}, weight = 2, d_min = 0.1, d_max = 1}, - {{name = "constant-combinator", count = math_random(4,8)}, weight = 2, d_min = 0.1, d_max = 1}, - {{name = "decider-combinator", count = math_random(4,8)}, weight = 2, d_min = 0.1, d_max = 1}, - {{name = "power-switch", count = 1}, weight = 2, d_min = 0.1, d_max = 1}, - {{name = "programmable-speaker", count = math_random(2,4)}, weight = 1, d_min = 0.1, d_max = 1}, - {{name = "green-wire", count = math_random(10,29)}, weight = 4, d_min = 0.1, d_max = 1}, - {{name = "red-wire", count = math_random(10,29)}, weight = 4, d_min = 0.1, d_max = 1}, - {{name = "chemical-plant", count = math_random(1,3)}, weight = 3, d_min = 0.3, d_max = 1}, - {{name = "burner-mining-drill", count = math_random(2,4)}, weight = 3, d_min = 0.0, d_max = 0.2}, - {{name = "electric-mining-drill", count = math_random(2,4)}, weight = 3, d_min = 0.2, d_max = 1}, - {{name = "express-transport-belt", count = math_random(25,75)}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "express-underground-belt", count = math_random(4,8)}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "express-splitter", count = math_random(1,4)}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "fast-transport-belt", count = math_random(25,75)}, weight = 3, d_min = 0.2, d_max = 0.7}, - {{name = "fast-underground-belt", count = math_random(4,8)}, weight = 3, d_min = 0.2, d_max = 0.7}, - {{name = "fast-splitter", count = math_random(1,4)}, weight = 3, d_min = 0.2, d_max = 0.3}, - {{name = "transport-belt", count = math_random(25,75)}, weight = 3, d_min = 0, d_max = 0.3}, - {{name = "underground-belt", count = math_random(4,8)}, weight = 3, d_min = 0, d_max = 0.3}, - {{name = "splitter", count = math_random(1,4)}, weight = 3, d_min = 0, d_max = 0.3}, - --{{name = "oil-refinery", count = math_random(2,4)}, weight = 2, d_min = 0.3, d_max = 1}, - {{name = "pipe", count = math_random(30,50)}, weight = 3, d_min = 0.0, d_max = 0.3}, - {{name = "pipe-to-ground", count = math_random(4,8)}, weight = 1, d_min = 0.2, d_max = 0.5}, - {{name = "pumpjack", count = math_random(1,3)}, weight = 1, d_min = 0.3, d_max = 0.8}, - {{name = "pump", count = math_random(1,2)}, weight = 1, d_min = 0.3, d_max = 0.8}, - {{name = "solar-panel", count = math_random(3,6)}, weight = 3, d_min = 0.4, d_max = 0.9}, - {{name = "electric-furnace", count = math_random(2,4)}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "steel-furnace", count = math_random(4,8)}, weight = 3, d_min = 0.2, d_max = 0.7}, - {{name = "stone-furnace", count = math_random(8,16)}, weight = 3, d_min = 0.0, d_max = 0.2}, - {{name = "radar", count = math_random(1,2)}, weight = 1, d_min = 0.1, d_max = 0.4}, - {{name = "rail-signal", count = math_random(8,16)}, weight = 2, d_min = 0.2, d_max = 0.8}, - {{name = "rail-chain-signal", count = math_random(8,16)}, weight = 2, d_min = 0.2, d_max = 0.8}, - {{name = "stone-wall", count = math_random(33,99)}, weight = 3, d_min = 0.0, d_max = 0.7}, - {{name = "gate", count = math_random(16,32)}, weight = 3, d_min = 0.0, d_max = 0.7}, - {{name = "storage-tank", count = math_random(2,6)}, weight = 3, d_min = 0.3, d_max = 0.6}, - {{name = "train-stop", count = math_random(1,2)}, weight = 1, d_min = 0.2, d_max = 0.7}, - {{name = "express-loader", count = math_random(1,2)}, weight = 1, d_min = 0.5, d_max = 1}, - {{name = "fast-loader", count = math_random(1,2)}, weight = 1, d_min = 0.2, d_max = 0.7}, - {{name = "loader", count = math_random(1,2)}, weight = 1, d_min = 0.0, d_max = 0.5}, - {{name = "lab", count = math_random(1,2)}, weight = 2, d_min = 0.0, d_max = 0.3}, - {{name = "roboport", count = 1}, weight = 2, d_min = 0.8, d_max = 1}, - {{name = "flamethrower-turret", count = 1}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "laser-turret", count = math_random(3,6)}, weight = 3, d_min = 0.5, d_max = 1}, - {{name = "gun-turret", count = math_random(2,4)}, weight = 3, d_min = 0.2, d_max = 0.9}, - } - local jumps = 0 - if objective.chronojumps then jumps = objective.chronojumps end - local distance_to_center = (jumps / 40) + local distance_to_center = (jumps / 40) if distance_to_center > 1 then distance_to_center = 1 end - for _, t in pairs (chest_loot) do - for _ = 1, t.weight, 1 do - --if math_random(1,50) == 1 then log(distance_to_center) end - if t.d_min <= distance_to_center and t.d_max >= distance_to_center then - table.insert(chest_raffle, t[1]) + local loot_data = treasure_chest_loot(difficulty, objective.planet[1]) + local loot_types, loot_weights = {}, {} + for i = 1,#loot_data,1 do + table.insert(loot_types, {["name"] = loot_data[i].name, ["min_count"] = loot_data[i].min_count, ["max_count"] = loot_data[i].max_count}) + + if loot_data[i].scaling then -- scale down weights away from the midpoint 'peak' (without changing the mean) + local midpoint = (loot_data[i].d_max + loot_data[i].d_min) / 2 + local difference = (loot_data[i].d_max - loot_data[i].d_min) + table.insert(loot_weights,loot_data[i].weight * math_max(0, 1 - (math_abs(distance_to_center - midpoint) / (difference / 2)))) + else -- no scaling + if loot_data[i].d_min <= distance_to_center and loot_data[i].d_max >= distance_to_center then + table.insert(loot_weights, loot_data[i].weight) + else + table.insert(loot_weights, 0) end end end @@ -181,9 +308,20 @@ function Public.treasure_chest(surface, position, container_name) local e = surface.create_entity({name = container_name, position=position, force="neutral", create_build_effect_smoke = false}) e.minable = false local i = e.get_inventory(defines.inventory.chest) - for _ = 1, math_random(2,6), 1 do - local loot = chest_raffle[math_random(1,#chest_raffle)] - i.insert(loot) + for _ = 1, math_random(2,5), 1 do -- 20/04/04: max 5 items better than 6, so that if you observe 4 items in alt-mode the chance of an extra one is 1/2 rather than 2/3 + local loot = Rand.raffle(loot_types,loot_weights) + local difficulty_scaling = Balance.treasure_quantity_difficulty_scaling(difficulty) + if objective.chronojumps == 0 then difficulty_scaling = 1 end + local low = math_max(1, math_ceil(loot.min_count * difficulty_scaling)) + local high = math_max(1, math_ceil(loot.max_count * difficulty_scaling)) + local _count = math_random(low, high) + local lucky = math_random(1,180) + if lucky == 1 then --lucky + _count = _count * 3 + elseif lucky <= 10 then + _count = _count * 2 + end + i.insert({name = loot.name, count = _count}) end end diff --git a/maps/chronosphere/upgrade_list.lua b/maps/chronosphere/upgrade_list.lua index 5a9cdae6..fd715fc3 100644 --- a/maps/chronosphere/upgrade_list.lua +++ b/maps/chronosphere/upgrade_list.lua @@ -1,4 +1,5 @@ local Chrono_table = require 'maps.chronosphere.table' +local Balance = require 'maps.chronosphere.balance' local Difficulty = require 'modules.difficulty_vote' local Public = {} @@ -9,363 +10,233 @@ local math_abs = math.abs local math_ceil = math.ceil function Public.upgrades() - local Diff = Difficulty.get() - local objective = Chrono_table.get_table() - if not objective.upgrades then - objective.upgrades = {} - for i = 1, 16, 1 do - objective.upgrades[i] = 0 - end - end - if not Diff.difficulty_vote_value then - Diff.difficulty_vote_value = 1 + local objective = Chrono_table.get_table() + local difficulty = Difficulty.get().difficulty_vote_value + if not objective.upgrades then + objective.upgrades = {} + for i = 1, 16, 1 do + objective.upgrades[i] = 0 end + end - --Each upgrade is automatically added into gui. - --name : visible name in gui (best if localized) - --sprite: visible icon - --cost/item/tt = the first part of localized string, for example coin is in item-name.coin. Can be even scenario's key. - --Second part of localized string is taken from item's name. - --First additional parameter for tooltip should match the max_level - --still need to map upgrade effects in upgrades.lua / process_upgrade() if it should do more than increase level of upgrade - local upgrades = { - [1] = { - name = {'chronosphere.upgrade_train_armor'}, - sprite = 'recipe/locomotive', - max_level = 36, - message = {'chronosphere.upgrade_train_armor_message'}, - tooltip = {'chronosphere.upgrade_train_armor_tooltip', 36, objective.max_health}, - jump_limit = objective.upgrades[1], - cost = { - item1 = { - name = 'coin', - tt = 'item-name', - sprite = 'item/coin', - count = 500 * (1 + objective.upgrades[1]) - }, - item2 = {name = 'copper-plate', tt = 'item-name', sprite = 'item/copper-plate', count = 1500} - } - }, - [2] = { - name = {'chronosphere.upgrade_filter'}, - sprite = 'recipe/effectivity-module', - max_level = 9, - message = {'chronosphere.upgrade_filter_message'}, - tooltip = { - 'chronosphere.upgrade_filter_tooltip', - math_floor(300 / (objective.upgrades[2] / 3 + 1) * Diff.difficulty_vote_value) - }, - jump_limit = (1 + objective.upgrades[2]) * 3 or 0, - cost = { - item1 = {name = 'coin', tt = 'item-name', sprite = 'item/coin', count = 5000}, - item2 = { - name = 'electronic-circuit', - tt = 'item-name', - sprite = 'item/electronic-circuit', - count = math_min(1 + objective.upgrades[2], 3) * 500 + 500 - }, - item3 = { - name = 'advanced-circuit', - tt = 'item-name', - sprite = 'item/advanced-circuit', - count = math_max(math_min(1 + objective.upgrades[2], 6) - 3, 0) * 500 - }, - item4 = { - name = 'processing-unit', - tt = 'item-name', - sprite = 'item/processing-unit', - count = math_max(math_min(1 + objective.upgrades[2], 9) - 6, 0) * 500 - } - } - }, - [3] = { - name = {'chronosphere.upgrade_accumulators'}, - sprite = 'recipe/accumulator', - max_level = 24, - message = {'chronosphere.upgrade_accumulators_message'}, - tooltip = {'chronosphere.upgrade_accumulators_tooltip'}, - jump_limit = objective.upgrades[3], - cost = { - item1 = { - name = 'coin', - tt = 'item-name', - sprite = 'item/coin', - count = 2000 * (1 + objective.upgrades[3] / 4) - }, - item2 = { - name = 'battery', - tt = 'item-name', - sprite = 'item/battery', - count = 100 * (1 + objective.upgrades[3]) - } - } - }, - [4] = { - name = {'chronosphere.upgrade_loot_pickup'}, - sprite = 'recipe/long-handed-inserter', - max_level = 4, - message = {'chronosphere.upgrade_loot_pickup_message'}, - tooltip = {'chronosphere.upgrade_loot_pickup_tooltip', objective.upgrades[4]}, - jump_limit = 0, - cost = { - item1 = { - name = 'coin', - tt = 'item-name', - sprite = 'item/coin', - count = 1000 * (1 + objective.upgrades[4]) - }, - item2 = { - name = 'long-handed-inserter', - tt = 'entity-name', - sprite = 'recipe/long-handed-inserter', - count = 400 - } - } - }, - [5] = { - name = {'chronosphere.upgrade_inventory_size'}, - sprite = 'entity/character', - max_level = 4, - message = {'chronosphere.upgrade_inventory_size_message'}, - tooltip = {'chronosphere.upgrade_inventory_size_tooltip'}, - jump_limit = (1 + objective.upgrades[5]) * 5, - cost = { - item1 = { - name = 'coin', - tt = 'item-name', - sprite = 'item/coin', - count = 2500 * (1 + objective.upgrades[5]) - }, - item2 = { - name = 'wooden-chest', - tt = 'entity-name', - sprite = 'item/wooden-chest', - count = math_max(0, 250 - math_abs(objective.upgrades[5]) * 250) - }, - item3 = { - name = 'iron-chest', - tt = 'entity-name', - sprite = 'item/iron-chest', - count = math_max(0, 250 - math_abs(objective.upgrades[5] - 1) * 250) - }, - item4 = { - name = 'steel-chest', - tt = 'entity-name', - sprite = 'item/steel-chest', - count = math_max(0, 250 - math_abs(objective.upgrades[5] - 2) * 250) - }, - item5 = { - name = 'logistic-chest-storage', - tt = 'entity-name', - sprite = 'item/logistic-chest-storage', - count = math_max(0, 250 - math_abs(objective.upgrades[5] - 3) * 250) - } - } - }, - [6] = { - name = {'chronosphere.upgrade_repair'}, - sprite = 'recipe/repair-pack', - max_level = 4, - message = {'chronosphere.upgrade_repair_message'}, - tooltip = {'chronosphere.upgrade_repair_tooltip', objective.upgrades[6]}, - jump_limit = 0, - cost = { - item1 = { - name = 'coin', - tt = 'item-name', - sprite = 'item/coin', - count = 1000 * (1 + objective.upgrades[6]) - }, - item2 = { - name = 'repair-pack', - tt = 'item-name', - sprite = 'recipe/repair-pack', - count = 200 * (1 + objective.upgrades[6]) - } - } - }, - [7] = { - name = {'chronosphere.upgrade_water'}, - sprite = 'fluid/water', - max_level = 1, - message = {'chronosphere.upgrade_water_message'}, - tooltip = {'chronosphere.upgrade_water_tooltip'}, - jump_limit = 0, - cost = { - item1 = {name = 'coin', tt = 'item-name', sprite = 'item/coin', count = 2000}, - item2 = {name = 'pipe', tt = 'entity-name', sprite = 'item/pipe', count = 500}, - item3 = {name = 'pump', tt = 'entity-name', sprite = 'item/pump', count = 10} - } - }, - [8] = { - name = {'chronosphere.upgrade_output'}, - sprite = 'recipe/cargo-wagon', - max_level = 1, - message = {'chronosphere.upgrade_output_message'}, - tooltip = {'chronosphere.upgrade_output_tooltip'}, - jump_limit = 0, - cost = { - item1 = {name = 'coin', tt = 'item-name', sprite = 'item/coin', count = 2000}, - item2 = {name = 'fast-inserter', tt = 'entity-name', sprite = 'recipe/fast-inserter', count = 200} - } - }, - [9] = { - name = {'chronosphere.upgrade_storage'}, - sprite = 'item/logistic-chest-storage', - max_level = 4, - message = {'chronosphere.upgrade_storage_message'}, - tooltip = {'chronosphere.upgrade_storage_tooltip'}, - jump_limit = (1 + objective.upgrades[9]) * 5, - cost = { - item1 = { - name = 'coin', - tt = 'item-name', - sprite = 'item/coin', - count = 2500 * (1 + objective.upgrades[9]) - }, - item2 = { - name = 'wooden-chest', - tt = 'entity-name', - sprite = 'item/wooden-chest', - count = math_max(0, 250 - math_abs(objective.upgrades[9]) * 250) - }, - item3 = { - name = 'iron-chest', - tt = 'entity-name', - sprite = 'item/iron-chest', - count = math_max(0, 250 - math_abs(objective.upgrades[9] - 1) * 250) - }, - item4 = { - name = 'steel-chest', - tt = 'entity-name', - sprite = 'item/steel-chest', - count = math_max(0, 250 - math_abs(objective.upgrades[9] - 2) * 250) - }, - item5 = { - name = 'logistic-chest-storage', - tt = 'entity-name', - sprite = 'item/logistic-chest-storage', - count = math_max(0, 250 - math_abs(objective.upgrades[9] - 3) * 250) - } - } - }, - [10] = { - name = {'chronosphere.upgrade_poison'}, - sprite = 'recipe/poison-capsule', - max_level = 4, - message = {'chronosphere.upgrade_poison_message'}, - tooltip = {'chronosphere.upgrade_poison_tooltip', math_ceil(objective.poisontimeout / 6)}, - jump_limit = 0, - cost = { - item1 = {name = 'coin', tt = 'item-name', sprite = 'item/coin', count = 1000}, - item2 = {name = 'poison-capsule', tt = 'item-name', sprite = 'recipe/poison-capsule', count = 50} - } - }, - [11] = { - name = {'chronosphere.upgrade_fusion'}, - sprite = 'recipe/fusion-reactor-equipment', - max_level = 999, - message = {'chronosphere.upgrade_fusion_message'}, - tooltip = {'chronosphere.upgrade_fusion_tooltip'}, - jump_limit = 24, - cost = { - item1 = { - name = 'low-density-structure', - tt = 'item-name', - sprite = 'item/low-density-structure', - count = 100 - }, - item2 = {name = 'railgun-dart', tt = 'item-name', sprite = 'item/railgun-dart', count = 200}, - item3 = { - name = 'solar-panel-equipment', - tt = 'equipment-name', - sprite = 'item/solar-panel-equipment', - count = 16 - } - } - }, - [12] = { - name = {'chronosphere.upgrade_mk2'}, - sprite = 'recipe/power-armor-mk2', - max_level = 999, - message = {'chronosphere.upgrade_mk2_message'}, - tooltip = {'chronosphere.upgrade_mk2_tooltip'}, - jump_limit = 24, - cost = { - item1 = { - name = 'low-density-structure', - tt = 'item-name', - sprite = 'item/low-density-structure', - count = 100 - }, - item2 = {name = 'railgun-dart', tt = 'item-name', sprite = 'item/railgun-dart', count = 300}, - item3 = {name = 'power-armor', tt = 'item-name', sprite = 'item/power-armor', count = 1} - } - }, - [13] = { - name = {'chronosphere.upgrade_computer1'}, - sprite = 'item/advanced-circuit', - max_level = 1, - message = {'chronosphere.upgrade_computer1_message'}, - tooltip = {'chronosphere.upgrade_computer1_tooltip'}, - jump_limit = 15, - cost = { - item1 = {name = 'coin', tt = 'item-name', sprite = 'item/coin', count = 5000}, - item2 = {name = 'advanced-circuit', tt = 'item-name', sprite = 'item/advanced-circuit', count = 1000}, - item3 = {name = 'copper-plate', tt = 'item-name', sprite = 'item/copper-plate', count = 2000} - } - }, - [14] = { - name = {'chronosphere.upgrade_computer2'}, - sprite = 'item/processing-unit', - max_level = 1, - message = {'chronosphere.upgrade_computer2_message'}, - tooltip = {'chronosphere.upgrade_computer2_tooltip'}, - jump_limit = 20, - cost = { - item1 = {name = 'coin', tt = 'item-name', sprite = 'item/coin', count = 10000}, - item2 = {name = 'processing-unit', tt = 'item-name', sprite = 'item/processing-unit', count = 1000}, - item3 = {name = 'nuclear-reactor', tt = 'entity-name', sprite = 'item/nuclear-reactor', count = 1} - } - }, - [15] = { - name = {'chronosphere.upgrade_computer3'}, - sprite = 'item/rocket-control-unit', - max_level = 10, - message = {'chronosphere.upgrade_computer3_message', objective.upgrades[15] + 1}, - tooltip = {'chronosphere.upgrade_computer3_tooltip'}, - jump_limit = 25, - cost = { - item1 = {name = 'coin', tt = 'item-name', sprite = 'item/coin', count = 2000}, - item2 = { - name = 'low-density-structure', - tt = 'item-name', - sprite = 'item/low-density-structure', - count = 100 - }, - item3 = { - name = 'rocket-control-unit', - tt = 'item-name', - sprite = 'item/rocket-control-unit', - count = 100 - }, - item4 = {name = 'uranium-fuel-cell', tt = 'item-name', sprite = 'item/uranium-fuel-cell', count = 50} - } - }, - [16] = { - name = {'chronosphere.upgrade_computer4'}, - sprite = 'item/satellite', - max_level = 1, - message = {'chronosphere.upgrade_computer4_message'}, - tooltip = {'chronosphere.upgrade_computer4_tooltip'}, - jump_limit = 25, - cost = { - item1 = {name = 'rocket-silo', tt = 'entity-name', sprite = 'item/rocket-silo', count = 1}, - item2 = {name = 'satellite', tt = 'item-name', sprite = 'item/satellite', count = 1} - } - } + --Each upgrade is automatically added into gui. + --name : visible name in gui (best if localized) + --sprite: visible icon + --cost/item/tt = the first part of localized string, for example coin is in item-name.coin. Can be even scenario's key. + --Second part of localized string is taken from item's name. + --First additional parameter for tooltip should match the max_level + --still need to map upgrade effects in upgrades.lua / process_upgrade() if it should do more than increase level of upgrade + local upgrades = { + [1] = { + name = {"chronosphere.upgrade_train_armor"}, + sprite = "recipe/locomotive", + max_level = 36, + message = {"chronosphere.upgrade_train_armor_message"}, + tooltip = {"chronosphere.upgrade_train_armor_tooltip", 36, objective.max_health}, + jump_limit = objective.upgrades[1], + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 500 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty) * (1 + 2 * objective.upgrades[1])}, + item2 = {name = "copper-plate", tt = "item-name", sprite = "item/copper-plate", count = 1500}, + } + }, + [2] = { + name = {"chronosphere.upgrade_filter"}, + sprite = "recipe/effectivity-module", + max_level = 9, + message = {"chronosphere.upgrade_filter_message"}, + tooltip = {"chronosphere.upgrade_filter_tooltip", math_floor(100 * Balance.machine_pollution_transfer_from_inside_factor(Difficulty.get().difficulty_vote_value, objective.upgrades[2]))}, + jump_limit = (1 + objective.upgrades[2]) * 3 or 0, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 5000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty)}, + item2 = {name = "electronic-circuit", tt = "item-name", sprite = "item/electronic-circuit", count = math_min(1 + objective.upgrades[2], 3) * 500 + 500}, + item3 = {name = "advanced-circuit", tt = "item-name", sprite = "item/advanced-circuit", count = math_max(math_min(1 + objective.upgrades[2], 6) - 3, 0) * 500}, + item4 = {name = "processing-unit", tt = "item-name", sprite = "item/processing-unit", count = math_max(math_min(1 + objective.upgrades[2], 9) - 6, 0) * 500} + } + }, + [3] = { + name = {"chronosphere.upgrade_accumulators"}, + sprite = "recipe/accumulator", + max_level = 24, + message = {"chronosphere.upgrade_accumulators_message"}, + tooltip = {"chronosphere.upgrade_accumulators_tooltip"}, + jump_limit = objective.upgrades[3], + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 3000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty) * (1 + objective.upgrades[3] / 4)}, + item2 = {name = "battery", tt = "item-name", sprite = "item/battery", count = 100 * (1 + objective.upgrades[3])} + } + }, + [4] = { + name = {"chronosphere.upgrade_loot_pickup"}, + sprite = "recipe/long-handed-inserter", + max_level = 4, + message = {"chronosphere.upgrade_loot_pickup_message"}, + tooltip = {"chronosphere.upgrade_loot_pickup_tooltip", objective.upgrades[4]}, + jump_limit = 0, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 1000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty) * (1 + objective.upgrades[4])}, + item2 = {name = "long-handed-inserter", tt = "entity-name", sprite = "recipe/long-handed-inserter", count = 400} + } + }, + [5] = { + name = {"chronosphere.upgrade_inventory_size"}, + sprite = "entity/character", + max_level = 4, + message = {"chronosphere.upgrade_inventory_size_message"}, + tooltip = {"chronosphere.upgrade_inventory_size_tooltip"}, + jump_limit = (1 + objective.upgrades[5]) * 5, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 2500 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty) * (1 + objective.upgrades[5])}, + item2 = {name = "wooden-chest", tt = "entity-name", sprite = "item/wooden-chest", count = math_max(0, 250 - math_abs(objective.upgrades[5]) * 250)}, + item3 = {name = "iron-chest", tt = "entity-name", sprite = "item/iron-chest", count = math_max(0, 250 - math_abs(objective.upgrades[5] - 1) * 250)}, + item4 = {name = "steel-chest", tt = "entity-name", sprite = "item/steel-chest", count = math_max(0, 250 - math_abs(objective.upgrades[5] - 2) * 250)}, + item5 = {name = "logistic-chest-storage", tt = "entity-name", sprite = "item/logistic-chest-storage", count = math_max(0, 250 - math_abs(objective.upgrades[5] - 3) * 250)} + } + }, + [6] = { + name = {"chronosphere.upgrade_repair"}, + sprite = "recipe/repair-pack", + max_level = 4, + message = {"chronosphere.upgrade_repair_message"}, + tooltip = {"chronosphere.upgrade_repair_tooltip", objective.upgrades[6]}, + jump_limit = 0, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 1000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty) * (1 + objective.upgrades[6])}, + item2 = {name = "repair-pack", tt = "item-name", sprite = "recipe/repair-pack", count = 200 * (1 + objective.upgrades[6])} + } + }, + [7] = { + name = {"chronosphere.upgrade_water"}, + sprite = "fluid/water", + max_level = 1, + message = {"chronosphere.upgrade_water_message"}, + tooltip = {"chronosphere.upgrade_water_tooltip"}, + jump_limit = 0, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 2000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty)}, + item2 = {name = "pipe", tt = "entity-name", sprite = "item/pipe", count = 500}, + item3 = {name = "pump", tt = "entity-name", sprite = "item/pump", count = 10} + } + }, + [8] = { + name = {"chronosphere.upgrade_output"}, + sprite = "recipe/cargo-wagon", + max_level = 1, + message = {"chronosphere.upgrade_output_message"}, + tooltip = {"chronosphere.upgrade_output_tooltip"}, + jump_limit = 0, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 2000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty)}, + item2 = {name = "fast-inserter", tt = "entity-name", sprite = "recipe/fast-inserter", count = 200} + } + }, + [9] = { + name = {"chronosphere.upgrade_storage"}, + sprite = "item/logistic-chest-storage", + max_level = 4, + message = {"chronosphere.upgrade_storage_message"}, + tooltip = {"chronosphere.upgrade_storage_tooltip"}, + jump_limit = (1 + objective.upgrades[9]) * 5, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 3000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty) * (1 + objective.upgrades[9])}, + item2 = {name = "wooden-chest", tt = "entity-name", sprite = "item/wooden-chest", count = math_max(0, 250 - math_abs(objective.upgrades[9]) * 250)}, + item3 = {name = "iron-chest", tt = "entity-name", sprite = "item/iron-chest", count = math_max(0, 250 - math_abs(objective.upgrades[9] - 1) * 250)}, + item4 = {name = "steel-chest", tt = "entity-name", sprite = "item/steel-chest", count = math_max(0, 250 - math_abs(objective.upgrades[9] - 2) * 250)}, + item5 = {name = "logistic-chest-storage", tt = "entity-name", sprite = "item/logistic-chest-storage", count = math_max(0, 250 - math_abs(objective.upgrades[9] - 3) * 250)} + } + }, + [10] = { + name = {"chronosphere.upgrade_poison"}, + sprite = "recipe/poison-capsule", + max_level = 4, + message = {"chronosphere.upgrade_poison_message"}, + tooltip = {"chronosphere.upgrade_poison_tooltip", math_ceil(objective.poisontimeout/6)}, + jump_limit = 0, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 1000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty)}, + item2 = {name = "poison-capsule", tt = "item-name", sprite = "recipe/poison-capsule", count = 50} + } + }, + [11] = { + name = {"chronosphere.upgrade_fusion"}, + sprite = "recipe/fusion-reactor-equipment", + max_level = 999, + message = {"chronosphere.upgrade_fusion_message"}, + tooltip = {"chronosphere.upgrade_fusion_tooltip"}, + jump_limit = 24, + cost = { + item1 = {name = "low-density-structure", tt = "item-name", sprite = "item/low-density-structure", count = 100}, + item2 = {name = "railgun-dart", tt = "item-name", sprite = "item/railgun-dart", count = 200}, + item3 = {name = "solar-panel-equipment", tt = "equipment-name", sprite = "item/solar-panel-equipment", count = 16} + } + }, + [12] = { + name = {"chronosphere.upgrade_mk2"}, + sprite = "recipe/power-armor-mk2", + max_level = 999, + message = {"chronosphere.upgrade_mk2_message"}, + tooltip = {"chronosphere.upgrade_mk2_tooltip"}, + jump_limit = 24, + cost = { + item1 = {name = "low-density-structure", tt = "item-name", sprite = "item/low-density-structure", count = 100}, + item2 = {name = "railgun-dart", tt = "item-name", sprite = "item/railgun-dart", count = 300}, + item3 = {name = "power-armor", tt = "item-name", sprite = "item/power-armor", count = 1} + } + }, + [13] = { + name = {"chronosphere.upgrade_computer1"}, + sprite = "item/advanced-circuit", + max_level = 1, + message = {"chronosphere.upgrade_computer1_message"}, + tooltip = {"chronosphere.upgrade_computer1_tooltip"}, + jump_limit = 15, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 5000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty)}, + item2 = {name = "advanced-circuit", tt = "item-name", sprite = "item/advanced-circuit", count = 800}, + item3 = {name = "copper-plate", tt = "item-name", sprite = "item/copper-plate", count = 2000} + } + }, + [14] = { + name = {"chronosphere.upgrade_computer2"}, + sprite = "item/processing-unit", + max_level = 1, + message = {"chronosphere.upgrade_computer2_message"}, + tooltip = {"chronosphere.upgrade_computer2_tooltip"}, + jump_limit = 20, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 10000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty)}, + item2 = {name = "processing-unit", tt = "item-name", sprite = "item/processing-unit", count = 800}, + item3 = {name = "nuclear-reactor", tt = "entity-name", sprite = "item/nuclear-reactor", count = 1} + } + }, + [15] = { + name = {"chronosphere.upgrade_computer3"}, + sprite = "item/rocket-control-unit", + max_level = 10, + message = {"chronosphere.upgrade_computer3_message", objective.upgrades[15] + 1}, + tooltip = {"chronosphere.upgrade_computer3_tooltip"}, + jump_limit = 25, + cost = { + item1 = {name = "coin", tt = "item-name", sprite = "item/coin", count = 2000 * Balance.upgrades_coin_cost_difficulty_scaling(difficulty)}, + item2 = {name = "low-density-structure", tt = "item-name", sprite = "item/low-density-structure", count = 40}, + item3 = {name = "rocket-control-unit", tt = "item-name", sprite = "item/rocket-control-unit", count = 40}, + item4 = {name = "uranium-fuel-cell", tt = "item-name", sprite = "item/uranium-fuel-cell", count = 20} + } + }, + [16] = { + name = {"chronosphere.upgrade_computer4"}, + sprite = "item/satellite", + max_level = 1, + message = {"chronosphere.upgrade_computer4_message"}, + tooltip = {"chronosphere.upgrade_computer4_tooltip"}, + jump_limit = 25, + cost = { + item1 = {name = "rocket-silo", tt = "entity-name", sprite = "item/rocket-silo", count = 1}, + item2 = {name = "satellite", tt = "item-name", sprite = "item/satellite", count = 1} + } } - return upgrades + + } + return upgrades end return Public diff --git a/maps/chronosphere/upgrades.lua b/maps/chronosphere/upgrades.lua index 34328a07..57ee6a30 100644 --- a/maps/chronosphere/upgrades.lua +++ b/maps/chronosphere/upgrades.lua @@ -20,10 +20,8 @@ local function check_win() objective.game_reset_tick = game.tick + 18000 objective.game_won = true objective.game_lost = true - objective.chronotimer = 200000000 - 300 - for _, player in pairs(game.connected_players) do - player.play_sound{path="utility/game_won", volume_modifier=0.85} - end + objective.chronocharges = 200000000 - 300 + game.play_sound{path="utility/game_won", volume_modifier=0.85} local message = {"chronosphere.message_game_won1"} local message2 = "Number of delivered fish: " .. objective.mainscore game.print(message, {r=0.98, g=0.66, b=0.22}) @@ -43,7 +41,7 @@ local function upgrade_hp() rendering.set_text(objective.health_text, "HP: " .. objective.health .. " / " .. objective.max_health) end -local function spawn_acumulators() +local function spawn_accumulators() local objective = Chrono_table.get_table() local x = -28 local y = -252 @@ -56,7 +54,7 @@ local function spawn_acumulators() local acumulator = surface.create_entity({name = "accumulator", position = {x + 2 * i, y + yy}, force="player", create_build_effect_smoke = false}) acumulator.minable = false acumulator.destructible = false - table.insert(objective.acumulators, acumulator) + table.insert(objective.accumulators, acumulator) end end @@ -167,7 +165,7 @@ local function process_upgrade(index) if index == 1 then upgrade_hp() elseif index == 3 then - spawn_acumulators() + spawn_accumulators() elseif index == 4 then upgrade_pickup() elseif index == 5 then @@ -236,7 +234,7 @@ function Public.check_upgrades() if not objective.upgradechest then return end if objective.game_lost == true then return end check_all_upgrades() - if objective.planet[1].name.id == 17 then + if objective.planet[1].type.id == 17 then if objective.fishchest then check_win() end @@ -251,7 +249,8 @@ function Public.trigger_poison() objective.poisontimeout = 120 local objs = {objective.locomotive, objective.locomotive_cargo[1], objective.locomotive_cargo[2], objective.locomotive_cargo[3]} local surface = objective.surface - game.print({"chronosphere.message_poison_defense"}, {r=0.98, g=0.66, b=0.22}) + game.print({"chronosphere.message_poison_defense"}, {r=0.98, g=0.66, b=0.22}) + Server.to_discord_embed("Triggering poison defense. Let's kill everything!") for i = 1, 4, 1 do surface.create_entity({name = "poison-capsule", position = objs[i].position, force = "player", target = objs[i], speed = 1 }) end diff --git a/modules/difficulty_vote.lua b/modules/difficulty_vote.lua index f000d0a3..a527fa77 100644 --- a/modules/difficulty_vote.lua +++ b/modules/difficulty_vote.lua @@ -83,6 +83,10 @@ function Public.set_difficulties(...) end end +function Public.set_poll_closing_timeout(...) + this.difficulty_poll_closing_timeout = ... +end + function Public.get() return this end