You've already forked ComfyFactorio
mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2026-06-20 16:32:28 +02:00
new map - pigeotto
This commit is contained in:
@@ -95,6 +95,7 @@ require 'modules.autostash'
|
||||
--require 'maps.mountain_fortress'
|
||||
|
||||
--![[Defend the market against waves of biters]]--
|
||||
--require 'maps.pidgeotto.main'
|
||||
--require 'maps.fish_defender_v2.main'
|
||||
--require 'maps.crab_defender.main'
|
||||
--require 'maps.fish_defender_v1.fish_defender'
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
[pidgeotto]
|
||||
map_info_main_caption=--Pidgeotto--
|
||||
map_info_sub_caption= ~~kr´r´r´r´rah~~
|
||||
map_info_text=The biters have caught the scent of fish in the market.\nFend them off as long as possible!\nThis however will not be an easy task,\nsince their strength and resistance increases constantly over time.\n\nYour ultimate goal is to evacuate all the fish!\nPut them in your rocket's cargo and launch them into space.\nDon't worry, you will still get space science.\n\nThe Market will gladly take any coin you might find.\nAdditional turret slots can be bought at the market.\nSeveral unique upgrades are available too.\nResearching tanks will unlock the artillery technology early.\nAny container bearing dangerous goods, like ammo, grenades or barrels,\ncauses heavy explosions when it breaks.\nMaybe this can be used to our advantage.
|
||||
boss_message=Boss Wave __1__ - - __2__
|
||||
50=The Big Biter Gang
|
||||
100=Biterzilla
|
||||
150=The Spitter Squad
|
||||
200=The Wall Nibblers
|
||||
250=Conveyor Munchers
|
||||
300=Furnace Freezers
|
||||
350=Cable Chewers
|
||||
400=Power Pole Thieves
|
||||
450=Assembler Annihilators
|
||||
500=Inserter Crunchers
|
||||
550=Engineer Eaters
|
||||
600=Belt Unbalancers
|
||||
650=Turret Devourers
|
||||
700=Pipe Perforators
|
||||
750=Desync Bros
|
||||
800=Ratio Randomizers
|
||||
850=Wire Chompers
|
||||
900=The Bus Mixers
|
||||
950=Roundabout Deadlockers
|
||||
1000=Happy Tree Friends
|
||||
1050=Uranium Digesters
|
||||
1100=Bot Banishers
|
||||
1150=Chest Crushers
|
||||
1200=Cargo Wagon Scratchers
|
||||
1250=Transport Belt Surfers
|
||||
1300=Pumpjack Pulverizers
|
||||
1350=Radar Ravagers
|
||||
1400=Mall Deconstrutors
|
||||
1450=Lamp Dimmers
|
||||
1500=Roboport Disablers
|
||||
1550=Signal Spammers
|
||||
1600=Brick Tramplers
|
||||
1650=Drill Destroyers
|
||||
1700=Gearwheel Grinders
|
||||
1750=Silo Seekers
|
||||
1800=Circuit Breakers
|
||||
1850=Bullet Absorbers
|
||||
1900=Oil Guzzlers
|
||||
1950=Belt Rotators
|
||||
2000=Bluescreen Factor
|
||||
@@ -0,0 +1,219 @@
|
||||
local simplex_noise = require 'utils.simplex_noise'.d2
|
||||
local map_data = require 'maps.pidgeotto.layout'
|
||||
|
||||
local random = math.random
|
||||
local abs = math.abs
|
||||
local floor = math.floor
|
||||
local scale = 1
|
||||
|
||||
local Public = {}
|
||||
|
||||
local tile_map = {
|
||||
[1] = false,
|
||||
[2] = true,
|
||||
[3] = 'concrete',
|
||||
[4] = 'deepwater-green',
|
||||
[5] = 'deepwater',
|
||||
[6] = 'dirt-1',
|
||||
[7] = 'dirt-2',
|
||||
[8] = 'dirt-3',
|
||||
[9] = 'dirt-4',
|
||||
[10] = 'dirt-5',
|
||||
[11] = 'dirt-6',
|
||||
[12] = 'dirt-7',
|
||||
[13] = 'dry-dirt',
|
||||
[14] = 'grass-1',
|
||||
[15] = 'grass-2',
|
||||
[16] = 'grass-3',
|
||||
[17] = 'grass-4',
|
||||
[18] = 'hazard-concrete-left',
|
||||
[19] = 'hazard-concrete-right',
|
||||
[20] = 'lab-dark-1',
|
||||
[21] = 'lab-dark-2',
|
||||
[22] = 'lab-white',
|
||||
[23] = 'out-of-map',
|
||||
[24] = 'red-desert-0',
|
||||
[25] = 'red-desert-1',
|
||||
[26] = 'red-desert-2',
|
||||
[27] = 'red-desert-3',
|
||||
[28] = 'sand-1',
|
||||
[29] = 'sand-2',
|
||||
[30] = 'sand-3',
|
||||
[31] = 'stone-path',
|
||||
[32] = 'water-green',
|
||||
[33] = 'water',
|
||||
[34] = 'water-shallow',
|
||||
[35] = 'black-refined-concrete'
|
||||
}
|
||||
|
||||
local rock_raffle = {
|
||||
'sand-rock-big',
|
||||
'sand-rock-big',
|
||||
'rock-big',
|
||||
'rock-big',
|
||||
'rock-big',
|
||||
'rock-big',
|
||||
'rock-big',
|
||||
'rock-big',
|
||||
'rock-huge'
|
||||
}
|
||||
|
||||
local function decompress()
|
||||
local decompressed = {}
|
||||
local data = map_data.data
|
||||
local height = map_data.height
|
||||
local width = map_data.width
|
||||
|
||||
for y = 1, height do
|
||||
local row = data[y]
|
||||
local u_row = {}
|
||||
decompressed[y] = u_row
|
||||
local x = 1
|
||||
for index = 1, #row, 2 do
|
||||
local pixel = row[index]
|
||||
local count = row[index + 1]
|
||||
|
||||
for _ = 1, count do
|
||||
u_row[x] = pixel
|
||||
x = x + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return decompressed, width, height
|
||||
end
|
||||
local tile_data, width, height = decompress()
|
||||
|
||||
local function get_pos(x, y)
|
||||
-- the plus one is because lua tables are one based.
|
||||
local half_width = floor(width / 2) + 1
|
||||
local half_height = floor(height / 2) + 1
|
||||
x = x / scale
|
||||
y = y / scale
|
||||
x = floor(x)
|
||||
y = floor(y)
|
||||
local x2 = x + half_width
|
||||
local y2 = y + half_height
|
||||
|
||||
if y2 > 0 and y2 <= height and x2 > 0 and x2 <= width then
|
||||
return tile_map[tile_data[y2][x2]]
|
||||
end
|
||||
end
|
||||
|
||||
local ores = {'coal', 'iron-ore', 'copper-ore', 'stone'}
|
||||
|
||||
local function plankton_territory(position, seed, ent)
|
||||
local noise = simplex_noise(position.x * 0.009, position.y * 0.009, seed)
|
||||
local d = 196
|
||||
|
||||
if get_pos(position.x, position.y) then
|
||||
return
|
||||
end
|
||||
|
||||
if position.x + position.y > (d * -1) - (abs(noise) * d * 3) and position.x > position.y - (d + (abs(noise) * d * 3)) then
|
||||
return 'out-of-map'
|
||||
end
|
||||
|
||||
local noise_2 = simplex_noise(position.x * 0.0075, position.y * 0.0075, seed + 10000)
|
||||
--if noise_2 > 0.87 then surface.set_tiles({{name = "deepwater-green", position = position}}, true) return true end
|
||||
if noise_2 > 0.87 then
|
||||
return 'deepwater-green'
|
||||
end
|
||||
if noise_2 > 0.75 then
|
||||
local i = floor(noise * 6) % 4 + 1
|
||||
--surface.set_tiles({{name = "grass-" .. i, position = position}}, true)
|
||||
ent[#ent + 1] = {name = ores[i], position = position, amount = 1 + 2500 * abs(noise_2 * 3)}
|
||||
return ('grass-' .. i)
|
||||
end
|
||||
if noise_2 < -0.76 then
|
||||
local i = floor(noise * 6) % 4 + 1
|
||||
--surface.set_tiles({{name = "grass-" .. i, position = position}}, true)
|
||||
if noise_2 < -0.86 then
|
||||
ent[#ent + 1] = {name = 'uranium-ore', position = position, amount = 1 + 1000 * abs(noise_2 * 2)}
|
||||
|
||||
return ('grass-' .. i)
|
||||
end
|
||||
if random(1, 3) ~= 1 then
|
||||
ent[#ent + 1] = {name = rock_raffle[random(1, #rock_raffle)], position = position}
|
||||
end
|
||||
return ('grass-' .. i)
|
||||
end
|
||||
|
||||
if noise < 0.12 and noise > -0.12 then
|
||||
local i = floor(noise * 32) % 4 + 1
|
||||
--surface.set_tiles({{name = "grass-" .. i, position = position}}, true)
|
||||
if random(1, 5) == 1 then
|
||||
ent[#ent + 1] = {name = rock_raffle[random(1, #rock_raffle)], position = position}
|
||||
end
|
||||
return ('grass-' .. i)
|
||||
end
|
||||
|
||||
--surface.set_tiles({{name = "water", position = position}}, true)
|
||||
if random(1, 128) == 1 then
|
||||
ent[#ent + 1] = {name = 'fish', position = position}
|
||||
end
|
||||
|
||||
return 'water'
|
||||
end
|
||||
|
||||
local function get_random_ore(position)
|
||||
local noise = (position.x * 0.009)
|
||||
local i = floor(noise * 6) % 4 + 1
|
||||
local ore = ores[i]
|
||||
|
||||
return ore
|
||||
end
|
||||
|
||||
function Public.make_chunk(event)
|
||||
local map_name = 'pidgeotto'
|
||||
|
||||
if string.sub(event.surface.name, 0, #map_name) ~= map_name then
|
||||
return
|
||||
end
|
||||
|
||||
local surface = event.surface
|
||||
|
||||
local x1 = event.area.left_top.x
|
||||
local y1 = event.area.left_top.y
|
||||
local x2 = event.area.right_bottom.x
|
||||
local y2 = event.area.right_bottom.y
|
||||
|
||||
local seed = game.surfaces[1].map_gen_settings.seed
|
||||
|
||||
local noise = {}
|
||||
local tiles = {}
|
||||
local ent = {}
|
||||
|
||||
for x = x1, x2 do
|
||||
for y = y1, y2 do
|
||||
local pos = {x = x, y = y}
|
||||
local new = get_pos(x, y)
|
||||
local ore = get_random_ore(pos)
|
||||
|
||||
if new and type(new) == 'string' then
|
||||
if new == 'lab-dark-2' then
|
||||
ent[#ent + 1] = {name = ore, position = pos, amount = 2500}
|
||||
else
|
||||
tiles[#tiles + 1] = {name = new, position = pos}
|
||||
end
|
||||
else
|
||||
local tile_to_set = plankton_territory(pos, seed, ent)
|
||||
if tile_to_set then
|
||||
noise[#noise + 1] = {name = tile_to_set, position = pos}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles, true)
|
||||
surface.set_tiles(noise, true)
|
||||
for i = 1, #ent do
|
||||
if ent[i].amount then
|
||||
surface.create_entity({name = ent[i].name, position = ent[i].position, amount = ent[i].amount})
|
||||
else
|
||||
surface.create_entity({name = ent[i].name, position = ent[i].position})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
||||
@@ -0,0 +1,99 @@
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
|
||||
local boss_biter = {}
|
||||
local math_random = math.random
|
||||
local radius = 6
|
||||
local targets = {}
|
||||
local acid_splashes = {
|
||||
['big-biter'] = 'acid-stream-worm-medium',
|
||||
['behemoth-biter'] = 'acid-stream-worm-big',
|
||||
['big-spitter'] = 'acid-stream-worm-medium',
|
||||
['behemoth-spitter'] = 'acid-stream-worm-big'
|
||||
}
|
||||
local acid_lines = {
|
||||
['big-spitter'] = 'acid-stream-spitter-medium',
|
||||
['behemoth-spitter'] = 'acid-stream-spitter-big'
|
||||
}
|
||||
for x = radius * -1, radius, 1 do
|
||||
for y = radius * -1, radius, 1 do
|
||||
if math.sqrt(x ^ 2 + y ^ 2) <= radius then
|
||||
targets[#targets + 1] = {x = x, y = y}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function acid_nova(event)
|
||||
for _ = 1, math.random(16, 32) do
|
||||
local i = math.random(1, #targets)
|
||||
event.entity.surface.create_entity(
|
||||
{
|
||||
name = acid_splashes[event.entity.name],
|
||||
position = event.entity.position,
|
||||
force = event.entity.force.name,
|
||||
source = event.entity.position,
|
||||
target = {x = event.entity.position.x + targets[i].x, y = event.entity.position.y + targets[i].y},
|
||||
max_range = radius,
|
||||
speed = 0.001
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
boss_biter.died = function(event)
|
||||
local acid_lines_delay = FDT.get('acid_lines_delay')
|
||||
if acid_splashes[event.entity.name] then
|
||||
acid_nova(event)
|
||||
end
|
||||
if acid_lines_delay[event.entity.unit_number] then
|
||||
FDT.get('acid_lines_delay')[event.entity.unit_number] = nil
|
||||
end
|
||||
FDT.get('boss_biters')[event.entity.unit_number] = nil
|
||||
end
|
||||
|
||||
local function acid_line(surface, name, source, target)
|
||||
local distance = math.sqrt((source.x - target.x) ^ 2 + (source.y - target.y) ^ 2)
|
||||
|
||||
if distance > 16 then
|
||||
return false
|
||||
end
|
||||
|
||||
local modifier = {(target.x - source.x) / distance, (target.y - source.y) / distance}
|
||||
|
||||
local position = {source.x, source.y}
|
||||
|
||||
for i = 1, distance + 4, 1 do
|
||||
if math_random(1, 3) == 1 then
|
||||
surface.create_entity(
|
||||
{
|
||||
name = name,
|
||||
position = source,
|
||||
force = 'enemy',
|
||||
source = source,
|
||||
target = position,
|
||||
max_range = 25,
|
||||
speed = 1
|
||||
}
|
||||
)
|
||||
end
|
||||
position = {position[1] + modifier[1], position[2] + modifier[2]}
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
boss_biter.damaged_entity = function(event)
|
||||
if acid_lines[event.cause.name] then
|
||||
local acid_lines_delay = FDT.get('acid_lines_delay')
|
||||
if not acid_lines_delay[event.cause.unit_number] then
|
||||
FDT.set('acid_lines_delay')[event.cause.unit_number] = 0
|
||||
end
|
||||
|
||||
if acid_lines_delay[event.cause.unit_number] < game.tick then
|
||||
if acid_line(event.cause.surface, acid_lines[event.cause.name], event.cause.position, event.entity.position) then
|
||||
FDT.set('acid_lines_delay')[event.cause.unit_number] = game.tick + 180
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return boss_biter
|
||||
@@ -0,0 +1,72 @@
|
||||
local radius = 9
|
||||
local math_random = math.random
|
||||
|
||||
local ammo_to_projectile_translation = {
|
||||
['shotgun-shell'] = 'shotgun-pellet',
|
||||
['piercing-shotgun-shell'] = 'piercing-shotgun-pellet'
|
||||
}
|
||||
|
||||
local function create_projectile(surface, position, target, name)
|
||||
surface.create_entity(
|
||||
{
|
||||
name = name,
|
||||
position = position,
|
||||
force = 'player',
|
||||
source = position,
|
||||
target = target,
|
||||
max_range = 16,
|
||||
speed = 0.3
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local function bounce(surface, position, ammo)
|
||||
if math_random(1, 3) ~= 1 then
|
||||
return
|
||||
end
|
||||
local valid_entities = {}
|
||||
for _, e in pairs(surface.find_entities_filtered({area = {{position.x - radius, position.y - radius}, {position.x + radius, position.y + radius}}})) do
|
||||
if e.health then
|
||||
if e.force.name ~= 'player' then
|
||||
--local distance_from_center = math_sqrt((e.position.x - position.x) ^ 2 + (e.position.y - position.y) ^ 2)
|
||||
--if distance_from_center <= radius then
|
||||
valid_entities[#valid_entities + 1] = e
|
||||
--end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not valid_entities[1] then
|
||||
return
|
||||
end
|
||||
|
||||
for _ = 1, math_random(3, 6), 1 do
|
||||
create_projectile(surface, position, valid_entities[math_random(1, #valid_entities)].position, ammo)
|
||||
end
|
||||
end
|
||||
|
||||
local function bouncy_shells(event)
|
||||
if event.damage_type.name ~= 'physical' then
|
||||
return false
|
||||
end
|
||||
local player = event.cause
|
||||
if player.shooting_state.state == defines.shooting.not_shooting then
|
||||
return false
|
||||
end
|
||||
local selected_weapon = player.get_inventory(defines.inventory.character_guns)[player.selected_gun_index]
|
||||
if selected_weapon.name ~= 'combat-shotgun' and selected_weapon.name ~= 'shotgun' then
|
||||
return false
|
||||
end
|
||||
|
||||
local selected_ammo = player.get_inventory(defines.inventory.character_ammo)[player.selected_gun_index]
|
||||
if not selected_ammo then
|
||||
return
|
||||
end
|
||||
if not ammo_to_projectile_translation[selected_ammo.name] then
|
||||
return
|
||||
end
|
||||
|
||||
bounce(player.surface, event.entity.position, ammo_to_projectile_translation[selected_ammo.name])
|
||||
end
|
||||
|
||||
return bouncy_shells
|
||||
@@ -0,0 +1,115 @@
|
||||
local Server = require 'utils.server'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
|
||||
local mapkeeper = '[color=blue]Mapkeeper:[/color]'
|
||||
|
||||
commands.add_command(
|
||||
'scenario',
|
||||
'Usable only for admins - controls the scenario!',
|
||||
function(cmd)
|
||||
local p
|
||||
local player = game.player
|
||||
|
||||
if not player or not player.valid then
|
||||
p = log
|
||||
else
|
||||
p = player.print
|
||||
if not player.admin then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local param = cmd.parameter
|
||||
|
||||
if param == 'restart' or param == 'shutdown' or param == 'reset' or param == 'restartnow' then
|
||||
goto continue
|
||||
else
|
||||
p('[ERROR] Arguments are:\nrestart\nshutdown\nreset\nrestartnow')
|
||||
return
|
||||
end
|
||||
|
||||
::continue::
|
||||
|
||||
local this = FDT.get()
|
||||
local reset_map = require 'maps.pidgeotto.main'.reset_game
|
||||
|
||||
if not this.reset_are_you_sure then
|
||||
this.reset_are_you_sure = true
|
||||
p('[WARNING] This command will disable the soft-reset feature, run this command again if you really want to do this!')
|
||||
return
|
||||
end
|
||||
|
||||
if param == 'restart' then
|
||||
if this.restart then
|
||||
this.reset_are_you_sure = nil
|
||||
this.restart = false
|
||||
this.soft_reset = true
|
||||
p('[SUCCESS] Soft-reset is enabled.')
|
||||
return
|
||||
else
|
||||
this.reset_are_you_sure = nil
|
||||
this.restart = true
|
||||
this.soft_reset = false
|
||||
if this.shutdown then
|
||||
this.shutdown = false
|
||||
end
|
||||
p('[WARNING] Soft-reset is disabled! Server will restart from scenario.')
|
||||
return
|
||||
end
|
||||
elseif param == 'restartnow' then
|
||||
this.reset_are_you_sure = nil
|
||||
p(player.name .. ' has restarted the game.')
|
||||
Server.start_scenario('pidgeotto')
|
||||
return
|
||||
elseif param == 'shutdown' then
|
||||
if this.shutdown then
|
||||
this.reset_are_you_sure = nil
|
||||
this.shutdown = false
|
||||
this.soft_reset = true
|
||||
p('[SUCCESS] Soft-reset is enabled.')
|
||||
return
|
||||
else
|
||||
this.reset_are_you_sure = nil
|
||||
this.shutdown = true
|
||||
this.soft_reset = false
|
||||
if this.restart then
|
||||
this.restart = false
|
||||
end
|
||||
p('[WARNING] Soft-reset is disabled! Server will shutdown.')
|
||||
return
|
||||
end
|
||||
elseif param == 'reset' then
|
||||
this.reset_are_you_sure = nil
|
||||
if player and player.valid then
|
||||
game.print(mapkeeper .. ' ' .. player.name .. ', has reset the game!', {r = 0.98, g = 0.66, b = 0.22})
|
||||
else
|
||||
game.print(mapkeeper .. ' server, has reset the game!', {r = 0.98, g = 0.66, b = 0.22})
|
||||
end
|
||||
reset_map()
|
||||
p('[WARNING] Game has been reset!')
|
||||
return
|
||||
end
|
||||
end
|
||||
)
|
||||
commands.add_command(
|
||||
'stop_generate_map',
|
||||
'Usable only for admins - controls the scenario!',
|
||||
function()
|
||||
local player = game.player
|
||||
|
||||
if player and player.valid then
|
||||
if not player.admin then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local stop_generating_map = FDT.get('stop_generating_map')
|
||||
if not stop_generating_map then
|
||||
FDT.set('stop_generating_map', true)
|
||||
player.print('Stopped generating the map!')
|
||||
else
|
||||
FDT.set('stop_generating_map', false)
|
||||
player.print('Resumed the generation of map!')
|
||||
end
|
||||
end
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
local math_random = math.random
|
||||
|
||||
local rock_raffle = {'sand-rock-big', 'rock-big', 'rock-big', 'rock-big', 'rock-huge'}
|
||||
|
||||
local function on_entity_died(event)
|
||||
local crumbly_walls_unlocked = FDT.get('crumbly_walls_unlocked')
|
||||
if not crumbly_walls_unlocked then
|
||||
return
|
||||
end
|
||||
local entity = event.entity
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
if entity.name ~= 'stone-wall' then
|
||||
return
|
||||
end
|
||||
if math_random(1, 4) == 1 then
|
||||
return
|
||||
end
|
||||
entity.surface.create_entity({name = rock_raffle[math_random(1, #rock_raffle)], position = entity.position, force = 'player'})
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_entity_died, on_entity_died)
|
||||
@@ -0,0 +1,42 @@
|
||||
local radius = 3
|
||||
|
||||
local function splash_damage(surface, position, final_damage_amount)
|
||||
local damage = math.random(math.floor(final_damage_amount * 3), math.floor(final_damage_amount * 4))
|
||||
for _, e in pairs(surface.find_entities_filtered({area = {{position.x - radius, position.y - radius}, {position.x + radius, position.y + radius}}})) do
|
||||
if e.valid and e.health then
|
||||
local distance_from_center = math.sqrt((e.position.x - position.x) ^ 2 + (e.position.y - position.y) ^ 2)
|
||||
if distance_from_center <= radius then
|
||||
local damage_distance_modifier = 1 - distance_from_center / radius
|
||||
if damage > 0 then
|
||||
if math.random(1, 3) == 1 then
|
||||
surface.create_entity({name = 'explosion', position = e.position})
|
||||
end
|
||||
e.damage(damage * damage_distance_modifier, 'player', 'explosion')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function explosive_bullets(event)
|
||||
if math.random(1, 3) ~= 1 then
|
||||
return false
|
||||
end
|
||||
if event.damage_type.name ~= 'physical' then
|
||||
return false
|
||||
end
|
||||
local player = event.cause
|
||||
if player.shooting_state.state == defines.shooting.not_shooting then
|
||||
return false
|
||||
end
|
||||
local selected_weapon = player.get_inventory(defines.inventory.character_guns)[player.selected_gun_index]
|
||||
if selected_weapon.name ~= 'submachine-gun' and selected_weapon.name ~= 'pistol' then
|
||||
return false
|
||||
end
|
||||
|
||||
player.surface.create_entity({name = 'explosion', position = event.entity.position})
|
||||
|
||||
splash_damage(player.surface, event.entity.position, event.final_damage_amount)
|
||||
end
|
||||
|
||||
return explosive_bullets
|
||||
@@ -0,0 +1,52 @@
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
local flame_boots = FDT.get('flame_boots')
|
||||
if not flame_boots then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
if not player.character then
|
||||
return
|
||||
end
|
||||
if player.character.driving then
|
||||
return
|
||||
end
|
||||
|
||||
if not flame_boots[player.index] then
|
||||
flame_boots[player.index] = {}
|
||||
end
|
||||
|
||||
if not flame_boots[player.index].fuel then
|
||||
return
|
||||
end
|
||||
|
||||
if flame_boots[player.index].fuel < 0 then
|
||||
player.print('Your flame boots have worn out.', {r = 0.22, g = 0.77, b = 0.44})
|
||||
flame_boots[player.index] = {}
|
||||
return
|
||||
end
|
||||
|
||||
if flame_boots[player.index].fuel % 500 == 0 then
|
||||
player.print('Fuel remaining: ' .. flame_boots[player.index].fuel, {r = 0.22, g = 0.77, b = 0.44})
|
||||
end
|
||||
|
||||
if not flame_boots[player.index].step_history then
|
||||
flame_boots[player.index].step_history = {}
|
||||
end
|
||||
|
||||
local elements = #flame_boots[player.index].step_history
|
||||
|
||||
flame_boots[player.index].step_history[elements + 1] = {x = player.position.x, y = player.position.y}
|
||||
|
||||
if elements < 50 then
|
||||
return
|
||||
end
|
||||
|
||||
player.surface.create_entity({name = 'fire-flame', position = flame_boots[player.index].step_history[elements - 2]})
|
||||
|
||||
flame_boots[player.index].fuel = flame_boots[player.index].fuel - 1
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
@@ -0,0 +1,37 @@
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
local radius = 32
|
||||
|
||||
local function on_player_used_capsule(event)
|
||||
local laser_pointer_unlocked = FDT.get('laser_pointer_unlocked')
|
||||
if not laser_pointer_unlocked then
|
||||
return
|
||||
end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
local position = event.position
|
||||
local used_item = event.item
|
||||
if used_item.name ~= 'artillery-targeting-remote' then
|
||||
return
|
||||
end
|
||||
|
||||
for _, unit in pairs(player.surface.find_enemy_units(position, radius, 'player')) do
|
||||
if math.random(1, 2) == 1 then
|
||||
unit.set_command(
|
||||
{
|
||||
type = defines.command.go_to_location,
|
||||
destination = position,
|
||||
radius = 2,
|
||||
distraction = defines.distraction.none,
|
||||
pathfind_flags = {
|
||||
allow_destroy_friendly_entities = false,
|
||||
prefer_straight_paths = false,
|
||||
low_priority = false
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_used_capsule, on_player_used_capsule)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,281 @@
|
||||
require 'maps.pidgeotto.flame_boots'
|
||||
require 'maps.pidgeotto.trapped_capsules'
|
||||
require 'maps.pidgeotto.ultra_mines'
|
||||
require 'maps.pidgeotto.crumbly_walls'
|
||||
require 'maps.pidgeotto.vehicle_nanobots'
|
||||
require 'maps.pidgeotto.laser_pointer'
|
||||
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
|
||||
local slot_upgrade_offers = {
|
||||
[1] = {'gun-turret', 'gun turret'},
|
||||
[2] = {'laser-turret', 'laser turret'},
|
||||
[3] = {'artillery-turret', 'artillery turret'},
|
||||
[4] = {'flamethrower-turret', 'flamethrower turret'},
|
||||
[5] = {'land-mine', 'land mine'}
|
||||
}
|
||||
|
||||
local special_descriptions = {
|
||||
['explosive-bullets'] = 'Unlock Explosive Bullets - Submachine-Gun and Pistol gains a chance to deal splash damage.',
|
||||
['bouncy-shells'] = 'Unlock Bouncy Shells - Shotgun projectiles may bounce to multiple targets.',
|
||||
['trapped-capsules'] = 'Unlock Trapped Capsules - Combat robots will send a last deadly projectile to a nearby enemy when killed.',
|
||||
['ultra-mines'] = 'Unlock Ultra Mines - Careful with these...',
|
||||
['crumbly-walls'] = 'Unlock Crumbly Walls - Fortifications which crumble, may turn into rocks.',
|
||||
['vehicle-nanobots'] = 'Unlock Vehicle Nanobots - Vehicles repair rapidly while driving.',
|
||||
['laser-pointer'] = 'Unlock Laser Pointer - The biters are on a quest to slay the red (artillery) dot.'
|
||||
}
|
||||
|
||||
local function refresh_market_offers()
|
||||
local market = FDT.get('market')
|
||||
if not market or not market.valid then
|
||||
return
|
||||
end
|
||||
for i = 1, 100, 1 do
|
||||
local a = market.remove_market_item(1)
|
||||
if a == false then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local entity_limits = FDT.get('entity_limits')
|
||||
|
||||
local str1 = 'Gun Turret Slot for ' .. tostring(entity_limits['gun-turret'].limit * entity_limits['gun-turret'].slot_price)
|
||||
str1 = str1 .. ' Coins.'
|
||||
|
||||
local str2 = 'Laser Turret Slot for ' .. tostring(entity_limits['laser-turret'].limit * entity_limits['laser-turret'].slot_price)
|
||||
str2 = str2 .. ' Coins.'
|
||||
|
||||
local str3 = 'Artillery Slot for ' .. tostring(entity_limits['artillery-turret'].limit * entity_limits['artillery-turret'].slot_price)
|
||||
str3 = str3 .. ' Coins.'
|
||||
|
||||
local current_limit = 1
|
||||
if entity_limits['flamethrower-turret'].limit ~= 0 then
|
||||
current_limit = current_limit + entity_limits['flamethrower-turret'].limit
|
||||
end
|
||||
local str4 = 'Flamethrower Turret Slot for ' .. tostring(current_limit * entity_limits['flamethrower-turret'].slot_price)
|
||||
str4 = str4 .. ' Coins.'
|
||||
|
||||
local str5 = 'Landmine Slot for ' .. tostring(math.ceil((entity_limits['land-mine'].limit / 3) * entity_limits['land-mine'].slot_price))
|
||||
str5 = str5 .. ' Coins.'
|
||||
|
||||
local market_items = {
|
||||
{price = {}, offer = {type = 'nothing', effect_description = str1}},
|
||||
{price = {}, offer = {type = 'nothing', effect_description = str2}},
|
||||
{price = {}, offer = {type = 'nothing', effect_description = str3}},
|
||||
{price = {}, offer = {type = 'nothing', effect_description = str4}},
|
||||
{price = {}, offer = {type = 'nothing', effect_description = str5}},
|
||||
{price = {{'coin', 5}}, offer = {type = 'give-item', item = 'raw-fish', count = 1}},
|
||||
{price = {{'coin', 1}}, offer = {type = 'give-item', item = 'wood', count = 8}},
|
||||
{price = {{'coin', 8}}, offer = {type = 'give-item', item = 'grenade', count = 1}},
|
||||
{price = {{'coin', 32}}, offer = {type = 'give-item', item = 'cluster-grenade', count = 1}},
|
||||
{price = {{'coin', 1}}, offer = {type = 'give-item', item = 'land-mine', count = 1}},
|
||||
{price = {{'coin', 80}}, offer = {type = 'give-item', item = 'car', count = 1}},
|
||||
{price = {{'coin', 1200}}, offer = {type = 'give-item', item = 'tank', count = 1}},
|
||||
{price = {{'coin', 3}}, offer = {type = 'give-item', item = 'cannon-shell', count = 1}},
|
||||
{price = {{'coin', 7}}, offer = {type = 'give-item', item = 'explosive-cannon-shell', count = 1}},
|
||||
{price = {{'coin', 50}}, offer = {type = 'give-item', item = 'gun-turret', count = 1}},
|
||||
{price = {{'coin', 300}}, offer = {type = 'give-item', item = 'laser-turret', count = 1}},
|
||||
{price = {{'coin', 450}}, offer = {type = 'give-item', item = 'artillery-turret', count = 1}},
|
||||
{price = {{'coin', 10}}, offer = {type = 'give-item', item = 'artillery-shell', count = 1}},
|
||||
{price = {{'coin', 25}}, offer = {type = 'give-item', item = 'artillery-targeting-remote', count = 1}},
|
||||
{price = {{'coin', 1}}, offer = {type = 'give-item', item = 'firearm-magazine', count = 1}},
|
||||
{price = {{'coin', 4}}, offer = {type = 'give-item', item = 'piercing-rounds-magazine', count = 1}},
|
||||
{price = {{'coin', 2}}, offer = {type = 'give-item', item = 'shotgun-shell', count = 1}},
|
||||
{price = {{'coin', 6}}, offer = {type = 'give-item', item = 'piercing-shotgun-shell', count = 1}},
|
||||
{price = {{'coin', 30}}, offer = {type = 'give-item', item = 'submachine-gun', count = 1}},
|
||||
{price = {{'coin', 250}}, offer = {type = 'give-item', item = 'combat-shotgun', count = 1}},
|
||||
{price = {{'coin', 450}}, offer = {type = 'give-item', item = 'flamethrower', count = 1}},
|
||||
{price = {{'coin', 25}}, offer = {type = 'give-item', item = 'flamethrower-ammo', count = 1}},
|
||||
{price = {{'coin', 125}}, offer = {type = 'give-item', item = 'rocket-launcher', count = 1}},
|
||||
{price = {{'coin', 2}}, offer = {type = 'give-item', item = 'rocket', count = 1}},
|
||||
{price = {{'coin', 7}}, offer = {type = 'give-item', item = 'explosive-rocket', count = 1}},
|
||||
{price = {{'coin', 7500}}, offer = {type = 'give-item', item = 'atomic-bomb', count = 1}},
|
||||
{price = {{'coin', 40}}, offer = {type = 'give-item', item = 'poison-capsule', count = 1}},
|
||||
{price = {{'coin', 4}}, offer = {type = 'give-item', item = 'defender-capsule', count = 1}},
|
||||
{price = {{'coin', 10}}, offer = {type = 'give-item', item = 'light-armor', count = 1}},
|
||||
{price = {{'coin', 125}}, offer = {type = 'give-item', item = 'heavy-armor', count = 1}},
|
||||
{price = {{'coin', 350}}, offer = {type = 'give-item', item = 'modular-armor', count = 1}},
|
||||
{price = {{'coin', 1500}}, offer = {type = 'give-item', item = 'power-armor', count = 1}},
|
||||
{price = {{'coin', 12000}}, offer = {type = 'give-item', item = 'power-armor-mk2', count = 1}},
|
||||
{price = {{'coin', 50}}, offer = {type = 'give-item', item = 'solar-panel-equipment', count = 1}},
|
||||
{price = {{'coin', 2250}}, offer = {type = 'give-item', item = 'fusion-reactor-equipment', count = 1}},
|
||||
{price = {{'coin', 100}}, offer = {type = 'give-item', item = 'battery-equipment', count = 1}},
|
||||
{price = {{'coin', 200}}, offer = {type = 'give-item', item = 'energy-shield-equipment', count = 1}},
|
||||
{price = {{'coin', 850}}, offer = {type = 'give-item', item = 'personal-laser-defense-equipment', count = 1}},
|
||||
{price = {{'coin', 175}}, offer = {type = 'give-item', item = 'exoskeleton-equipment', count = 1}},
|
||||
{price = {{'coin', 125}}, offer = {type = 'give-item', item = 'night-vision-equipment', count = 1}},
|
||||
{price = {{'coin', 200}}, offer = {type = 'give-item', item = 'belt-immunity-equipment', count = 1}},
|
||||
{price = {{'coin', 250}}, offer = {type = 'give-item', item = 'personal-roboport-equipment', count = 1}},
|
||||
{price = {{'coin', 35}}, offer = {type = 'give-item', item = 'construction-robot', count = 1}},
|
||||
{price = {{'coin', 25}}, offer = {type = 'give-item', item = 'cliff-explosives', count = 1}}
|
||||
}
|
||||
|
||||
for _, item in pairs(market_items) do
|
||||
market.add_market_item(item)
|
||||
end
|
||||
|
||||
if not FDT.get('trapped_capsules_unlocked') then
|
||||
market.add_market_item(
|
||||
{
|
||||
price = {{'coin', 3500}},
|
||||
offer = {type = 'nothing', effect_description = special_descriptions['trapped-capsules']}
|
||||
}
|
||||
)
|
||||
end
|
||||
if not FDT.get('explosive_bullets_unlocked') then
|
||||
market.add_market_item(
|
||||
{
|
||||
price = {{'coin', 4500}},
|
||||
offer = {type = 'nothing', effect_description = special_descriptions['explosive-bullets']}
|
||||
}
|
||||
)
|
||||
end
|
||||
if not FDT.get('bouncy_shells_unlocked') then
|
||||
market.add_market_item(
|
||||
{
|
||||
price = {{'coin', 10000}},
|
||||
offer = {type = 'nothing', effect_description = special_descriptions['bouncy-shells']}
|
||||
}
|
||||
)
|
||||
end
|
||||
if not FDT.get('vehicle_nanobots_unlocked') then
|
||||
market.add_market_item(
|
||||
{
|
||||
price = {{'coin', 15000}},
|
||||
offer = {type = 'nothing', effect_description = special_descriptions['vehicle-nanobots']}
|
||||
}
|
||||
)
|
||||
end
|
||||
--[[
|
||||
if not crumbly_walls_unlocked then
|
||||
market.add_market_item({price = {{"coin", 35000}}, offer = {type = 'nothing', effect_description = special_descriptions["crumbly-walls"]}})
|
||||
end
|
||||
if not ultra_mines_unlocked then
|
||||
market.add_market_item({price = {{"coin", 45000}}, offer = {type = 'nothing', effect_description = special_descriptions["ultra-mines"]}})
|
||||
end
|
||||
]]
|
||||
if not FDT.get('laser_pointer_unlocked') then
|
||||
market.add_market_item(
|
||||
{
|
||||
price = {{'coin', 65000}},
|
||||
offer = {type = 'nothing', effect_description = special_descriptions['laser-pointer']}
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function slot_upgrade(player, offer_index)
|
||||
local entity_limits = FDT.get('entity_limits')
|
||||
local price = entity_limits[slot_upgrade_offers[offer_index][1]].limit * entity_limits[slot_upgrade_offers[offer_index][1]].slot_price
|
||||
|
||||
local gain = 1
|
||||
if offer_index == 5 then
|
||||
price = math.ceil((entity_limits[slot_upgrade_offers[offer_index][1]].limit / 3) * entity_limits[slot_upgrade_offers[offer_index][1]].slot_price)
|
||||
gain = 3
|
||||
end
|
||||
|
||||
if slot_upgrade_offers[offer_index][1] == 'flamethrower-turret' then
|
||||
price = (entity_limits[slot_upgrade_offers[offer_index][1]].limit + 1) * entity_limits[slot_upgrade_offers[offer_index][1]].slot_price
|
||||
end
|
||||
|
||||
local coins_removed = player.remove_item({name = 'coin', count = price})
|
||||
if coins_removed ~= price then
|
||||
if coins_removed > 0 then
|
||||
player.insert({name = 'coin', count = coins_removed})
|
||||
end
|
||||
player.print('Not enough coins.', {r = 0.22, g = 0.77, b = 0.44})
|
||||
return false
|
||||
end
|
||||
|
||||
entity_limits[slot_upgrade_offers[offer_index][1]].limit = entity_limits[slot_upgrade_offers[offer_index][1]].limit + gain
|
||||
game.print(player.name .. ' has bought a ' .. slot_upgrade_offers[offer_index][2] .. ' slot for ' .. price .. ' coins!', {r = 0.22, g = 0.77, b = 0.44})
|
||||
|
||||
refresh_market_offers()
|
||||
end
|
||||
|
||||
local function on_market_item_purchased(event)
|
||||
local player = game.players[event.player_index]
|
||||
local market = event.market
|
||||
local offer_index = event.offer_index
|
||||
local offers = market.get_market_items()
|
||||
local bought_offer = offers[offer_index].offer
|
||||
if bought_offer.type ~= 'nothing' then
|
||||
return
|
||||
end
|
||||
|
||||
if slot_upgrade_offers[offer_index] then
|
||||
if slot_upgrade(player, offer_index) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if offer_index < 50 then
|
||||
return
|
||||
end
|
||||
|
||||
if bought_offer.effect_description == special_descriptions['explosive-bullets'] then
|
||||
game.print(player.name .. ' has unlocked explosive bullets.', {r = 0.22, g = 0.77, b = 0.44})
|
||||
FDT.set('explosive_bullets_unlocked', true)
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
|
||||
if bought_offer.effect_description == special_descriptions['bouncy-shells'] then
|
||||
game.print(player.name .. ' has unlocked bouncy shells.', {r = 0.22, g = 0.77, b = 0.44})
|
||||
FDT.set('bouncy_shells_unlocked', true)
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
|
||||
if bought_offer.effect_description == special_descriptions['trapped-capsules'] then
|
||||
game.print(player.name .. ' has unlocked trapped capsules!', {r = 0.22, g = 0.77, b = 0.44})
|
||||
FDT.set('trapped_capsules_unlocked', true)
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
|
||||
if bought_offer.effect_description == special_descriptions['ultra-mines'] then
|
||||
game.print(player.name .. ' has unlocked ultra mines!', {r = 0.22, g = 0.77, b = 0.44})
|
||||
FDT.set('ultra_mines_unlocked', true)
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
|
||||
if bought_offer.effect_description == special_descriptions['laser-pointer'] then
|
||||
game.print(player.name .. ' has unleashed the quest to slay the red dot!', {r = 0.22, g = 0.77, b = 0.44})
|
||||
FDT.set('laser_pointer_unlocked', true)
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
|
||||
if bought_offer.effect_description == special_descriptions['crumbly-walls'] then
|
||||
game.print(player.name .. ' has unlocked crumbly walls!', {r = 0.22, g = 0.77, b = 0.44})
|
||||
FDT.set('crumbly_walls_unlocked', true)
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
|
||||
if bought_offer.effect_description == special_descriptions['vehicle-nanobots'] then
|
||||
game.print(player.name .. ' has unlocked vehicle nanobots!', {r = 0.22, g = 0.77, b = 0.44})
|
||||
FDT.set('vehicle_nanobots_unlocked', true)
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local function on_gui_opened(event)
|
||||
if not event.entity then
|
||||
return
|
||||
end
|
||||
if not event.entity.valid then
|
||||
return
|
||||
end
|
||||
if event.entity.name == 'market' then
|
||||
refresh_market_offers()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)
|
||||
Event.add(defines.events.on_gui_opened, on_gui_opened)
|
||||
@@ -0,0 +1,55 @@
|
||||
require 'maps.pidgeotto.boss_biters'
|
||||
|
||||
local Event = require 'utils.event'
|
||||
local explosive_bullets = require 'maps.pidgeotto.explosive_gun_bullets'
|
||||
local bouncy_shells = require 'maps.pidgeotto.bouncy_shells'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
|
||||
local function protect_market(event)
|
||||
if event.entity.name ~= 'market' then
|
||||
return
|
||||
end
|
||||
if event.cause then
|
||||
if event.cause.force.name == 'enemy' then
|
||||
return
|
||||
end
|
||||
end
|
||||
event.entity.health = event.entity.health + event.final_damage_amount
|
||||
return true
|
||||
end
|
||||
|
||||
local function on_entity_damaged(event)
|
||||
if not event.entity then
|
||||
return
|
||||
end
|
||||
if not event.entity.valid then
|
||||
return
|
||||
end
|
||||
|
||||
if protect_market(event) then
|
||||
return
|
||||
end
|
||||
|
||||
if not event.cause then
|
||||
return
|
||||
end
|
||||
local explosive_bullets_unlocked = FDT.get('explosive_bullets_unlocked')
|
||||
local bouncy_shells_unlocked = FDT.get('bouncy_shells_unlocked')
|
||||
|
||||
if event.cause.name ~= 'character' then
|
||||
return
|
||||
end
|
||||
|
||||
if explosive_bullets_unlocked then
|
||||
if explosive_bullets(event) then
|
||||
return
|
||||
end
|
||||
end
|
||||
if bouncy_shells_unlocked then
|
||||
if bouncy_shells(event) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
|
||||
@@ -0,0 +1,29 @@
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
local gain_multiplier = 4
|
||||
|
||||
local function on_research_finished(event)
|
||||
local research = event.research
|
||||
local force_name = research.force.name
|
||||
local shotgun_shell_damage_modifier_old = FDT.get('shotgun_shell_damage_modifier_old')
|
||||
|
||||
if not shotgun_shell_damage_modifier_old[force_name] then
|
||||
shotgun_shell_damage_modifier_old[force_name] = game.forces[force_name].get_ammo_damage_modifier('shotgun-shell') - 0.1
|
||||
end
|
||||
|
||||
if string.sub(research.name, 0, 26) == 'physical-projectile-damage' then
|
||||
local current_damage = game.forces[force_name].get_ammo_damage_modifier('shotgun-shell')
|
||||
local vanilla_gain = current_damage - shotgun_shell_damage_modifier_old[force_name]
|
||||
local additional_gain = vanilla_gain * (gain_multiplier - 1)
|
||||
game.forces[force_name].set_ammo_damage_modifier('shotgun-shell', current_damage + additional_gain)
|
||||
end
|
||||
|
||||
shotgun_shell_damage_modifier_old[force_name] = game.forces[force_name].get_ammo_damage_modifier('shotgun-shell')
|
||||
end
|
||||
|
||||
local function on_init()
|
||||
game.forces.player.set_ammo_damage_modifier('shotgun-shell', 1)
|
||||
end
|
||||
|
||||
Event.on_init(on_init)
|
||||
Event.add(defines.events.on_research_finished, on_research_finished)
|
||||
@@ -0,0 +1,149 @@
|
||||
-- one table to rule them all!
|
||||
local Global = require 'utils.global'
|
||||
local Difficulty = require 'modules.difficulty_vote'
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local this = {}
|
||||
local Public = {}
|
||||
|
||||
Global.register(
|
||||
this,
|
||||
function(tbl)
|
||||
this = tbl
|
||||
end
|
||||
)
|
||||
|
||||
function Public.reset_table()
|
||||
-- @start
|
||||
-- these 3 are in case of stop/start/reloading the instance.
|
||||
this.soft_reset = true
|
||||
this.restart = false
|
||||
this.shutdown = false
|
||||
this.announced_message = false
|
||||
this.force_chunk = false
|
||||
this.chunk_load_tick = game.tick + 600
|
||||
-- @end
|
||||
this.game_has_ended = false
|
||||
this.game_reset = false
|
||||
this.spawn_area_generated = false
|
||||
this.results_sent = false
|
||||
|
||||
this.explosive_bullets_unlocked = false
|
||||
this.bouncy_shells_unlocked = false
|
||||
this.trapped_capsules_unlocked = false
|
||||
this.ultra_mines_unlocked = false
|
||||
this.laser_pointer_unlocked = false
|
||||
this.crumbly_walls_unlocked = false
|
||||
this.vehicle_nanobots_unlocked = false
|
||||
this.game_restart_timer = nil
|
||||
this.wave_count = 0
|
||||
this.wave_limit = 2000
|
||||
this.attack_wave_threat = nil
|
||||
this.market = nil
|
||||
this.market_age = nil
|
||||
this.last_reset = game.tick
|
||||
this.wave_interval = 3600
|
||||
this.wave_grace_period = game.tick + 72000
|
||||
-- this.wave_grace_period = game.tick + 3600
|
||||
this.boss_biters = {}
|
||||
this.acid_lines_delay = {}
|
||||
this.entity_limits = {
|
||||
['gun-turret'] = {placed = 1, limit = 1, str = 'gun turret', slot_price = 75},
|
||||
['laser-turret'] = {placed = 0, limit = 1, str = 'laser turret', slot_price = 300},
|
||||
['artillery-turret'] = {placed = 0, limit = 1, str = 'artillery turret', slot_price = 500},
|
||||
['flamethrower-turret'] = {placed = 0, limit = 0, str = 'flamethrower turret', slot_price = 50000},
|
||||
['land-mine'] = {placed = 0, limit = 1, str = 'mine', slot_price = 20}
|
||||
}
|
||||
this.difficulties_votes = {
|
||||
[1] = {wave_interval = 3800, amount_modifier = 0.92, strength_modifier = 0.85, boss_modifier = 5.0},
|
||||
[2] = {wave_interval = 3600, amount_modifier = 1.00, strength_modifier = 1.00, boss_modifier = 6.0},
|
||||
[3] = {wave_interval = 3400, amount_modifier = 1.08, strength_modifier = 1.25, boss_modifier = 7.0},
|
||||
[4] = {wave_interval = 3100, amount_modifier = 1.24, strength_modifier = 1.75, boss_modifier = 8.0},
|
||||
[5] = {wave_interval = 2700, amount_modifier = 1.48, strength_modifier = 2.50, boss_modifier = 9.0}
|
||||
}
|
||||
this.boss_waves = {
|
||||
[50] = {{name = 'big-biter', count = 3}},
|
||||
[100] = {{name = 'behemoth-biter', count = 1}},
|
||||
[150] = {{name = 'behemoth-spitter', count = 4}, {name = 'big-spitter', count = 16}},
|
||||
[200] = {
|
||||
{name = 'behemoth-biter', count = 4},
|
||||
{name = 'behemoth-spitter', count = 2},
|
||||
{name = 'big-biter', count = 32}
|
||||
},
|
||||
[250] = {
|
||||
{name = 'behemoth-biter', count = 8},
|
||||
{name = 'behemoth-spitter', count = 4},
|
||||
{name = 'big-spitter', count = 32}
|
||||
},
|
||||
[300] = {{name = 'behemoth-biter', count = 16}, {name = 'behemoth-spitter', count = 8}}
|
||||
}
|
||||
this.comfylatron_habitat = {
|
||||
left_top = {x = -1500, y = -1500},
|
||||
right_bottom = {x = -80, y = 1500}
|
||||
}
|
||||
this.shotgun_shell_damage_modifier_old = {}
|
||||
this.stop_generating_map = false
|
||||
end
|
||||
|
||||
function Public.get(key)
|
||||
if key then
|
||||
return this[key]
|
||||
else
|
||||
return this
|
||||
end
|
||||
end
|
||||
|
||||
function Public.set(key, value)
|
||||
if key and value == false then
|
||||
if this[key] then
|
||||
this[key] = false
|
||||
return this[key]
|
||||
end
|
||||
end
|
||||
if key and not value then
|
||||
if this[key] then
|
||||
this[key] = nil
|
||||
return
|
||||
end
|
||||
end
|
||||
if key and value then
|
||||
this[key] = value
|
||||
return this[key]
|
||||
end
|
||||
end
|
||||
|
||||
function Public.get_current_difficulty_wave_interval()
|
||||
local diff_index = Difficulty.get_difficulty_vote_index()
|
||||
if this.difficulties_votes[diff_index] then
|
||||
return this.difficulties_votes[diff_index].wave_interval
|
||||
end
|
||||
end
|
||||
|
||||
function Public.get_current_difficulty_boss_modifier()
|
||||
local diff_index = Difficulty.get_difficulty_vote_index()
|
||||
if this.difficulties_votes[diff_index] then
|
||||
return this.difficulties_votes[diff_index].boss_modifier
|
||||
end
|
||||
end
|
||||
|
||||
function Public.get_current_difficulty_strength_modifier()
|
||||
local diff_index = Difficulty.get_difficulty_vote_index()
|
||||
if this.difficulties_votes[diff_index] then
|
||||
return this.difficulties_votes[diff_index].strength_modifier
|
||||
end
|
||||
end
|
||||
|
||||
function Public.get_current_difficulty_amount_modifier()
|
||||
local diff_index = Difficulty.get_difficulty_vote_index()
|
||||
if this.difficulties_votes[diff_index] then
|
||||
return this.difficulties_votes[diff_index].amount_modifier
|
||||
end
|
||||
end
|
||||
|
||||
local on_init = function()
|
||||
Public.reset_table()
|
||||
end
|
||||
|
||||
Event.on_init(on_init)
|
||||
|
||||
return Public
|
||||
@@ -0,0 +1,302 @@
|
||||
local Event = require 'utils.event'
|
||||
local Builder = require 'maps.pidgeotto.b'
|
||||
local map_functions = require 'tools.map_functions'
|
||||
local simplex_noise = require 'utils.simplex_noise'.d2
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
local math_random = math.random
|
||||
local math_abs = math.abs
|
||||
local math_sqrt = math.sqrt
|
||||
|
||||
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 function get_replacement_tile(surface, position)
|
||||
for i = 1, 128, 1 do
|
||||
local vectors = {{0, i}, {0, i * -1}, {i, 0}, {i * -1, 0}}
|
||||
shuffle(vectors)
|
||||
for k, v in pairs(vectors) do
|
||||
local tile = surface.get_tile(position.x + v[1], position.y + v[2])
|
||||
if not tile.collides_with('resource-layer') then
|
||||
return tile.name
|
||||
end
|
||||
end
|
||||
end
|
||||
return 'grass-1'
|
||||
end
|
||||
|
||||
local function is_enemy_territory(p)
|
||||
if p.x - 64 < math_abs(p.y) then
|
||||
return false
|
||||
end
|
||||
--if p.x - 64 < p.y then return false end
|
||||
if p.x < 256 then
|
||||
return false
|
||||
end
|
||||
if p.x > 1024 then
|
||||
return false
|
||||
end
|
||||
if p.y > 512 then
|
||||
return false
|
||||
end
|
||||
if p.y < -512 then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function place_fish_market(surface, position)
|
||||
local market = surface.create_entity({name = 'market', position = position, force = 'player'})
|
||||
market.minable = false
|
||||
|
||||
return market
|
||||
end
|
||||
|
||||
local function enemy_territory(surface, left_top)
|
||||
if left_top.x < 256 then
|
||||
return
|
||||
end
|
||||
if left_top.x > 750 then
|
||||
return
|
||||
end
|
||||
if left_top.y > 766 then
|
||||
return
|
||||
end
|
||||
if left_top.y < -256 then
|
||||
return
|
||||
end
|
||||
|
||||
local area = {{left_top.x, left_top.y}, {left_top.x + 32, left_top.y + 32}}
|
||||
|
||||
if left_top.x > 300 then
|
||||
for x = 0, 31, 1 do
|
||||
for y = 0, 31, 1 do
|
||||
local pos = {x = left_top.x + x, y = left_top.y + y}
|
||||
if is_enemy_territory(pos) then
|
||||
if math_random(1, 512) == 1 then
|
||||
if surface.can_place_entity({name = 'biter-spawner', force = 'decoratives', position = pos}) then
|
||||
local entity
|
||||
if math_random(1, 4) == 1 then
|
||||
entity = surface.create_entity({name = 'spitter-spawner', force = 'decoratives', position = pos})
|
||||
else
|
||||
entity = surface.create_entity({name = 'biter-spawner', force = 'decoratives', position = pos})
|
||||
end
|
||||
entity.active = false
|
||||
entity.destructible = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for _, entity in pairs(surface.find_entities_filtered({area = area, type = {'tree', 'cliff'}})) do
|
||||
if is_enemy_territory(entity.position) then
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
for _, entity in pairs(surface.find_entities_filtered({area = area, type = 'resource'})) do
|
||||
if is_enemy_territory(entity.position) then
|
||||
surface.create_entity({name = 'uranium-ore', position = entity.position, amount = math_random(200, 8000)})
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
for _, tile in pairs(surface.find_tiles_filtered({name = {'water', 'deepwater'}, area = area})) do
|
||||
if is_enemy_territory(tile.position) then
|
||||
surface.set_tiles({{name = get_replacement_tile(surface, tile.position), position = {tile.position.x, tile.position.y}}}, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function fish_mouth(surface, left_top)
|
||||
if left_top.x > -1800 then
|
||||
return
|
||||
end
|
||||
if left_top.y > 64 then
|
||||
return
|
||||
end
|
||||
if left_top.y < -64 then
|
||||
return
|
||||
end
|
||||
if left_top.x < -2200 then
|
||||
return
|
||||
end
|
||||
|
||||
for x = 0, 31, 1 do
|
||||
for y = 0, 31, 1 do
|
||||
local pos = {x = left_top.x + x, y = left_top.y + y}
|
||||
local noise = simplex_noise(pos.x * 0.006, 0, game.surfaces[1].map_gen_settings.seed) * 20
|
||||
if pos.y <= 12 + noise and pos.y >= -12 + noise then
|
||||
surface.set_tiles({{name = 'water', position = pos}})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function generate_spawn_area(surface)
|
||||
local spawn_area_generated = FDT.get('spawn_area_generated')
|
||||
if spawn_area_generated then
|
||||
return
|
||||
end
|
||||
|
||||
surface.request_to_generate_chunks({0, 0}, 8)
|
||||
|
||||
local chunk_load_tick = FDT.get('chunk_load_tick')
|
||||
|
||||
if chunk_load_tick > game.tick then
|
||||
return
|
||||
end
|
||||
|
||||
local spawn_position_x = -128
|
||||
|
||||
surface.create_entity({name = 'electric-beam', position = {254, -90}, source = {254, -90}, target = {254, 134}})
|
||||
surface.create_entity({name = 'electric-beam', position = {159, -90}, source = {159, -90}, target = {254, -90}})
|
||||
|
||||
for _, tile in pairs(surface.find_tiles_filtered({name = {'water', 'deepwater'}, area = {{-300, -256}, {300, 300}}})) do
|
||||
local noise = math_abs(simplex_noise(tile.position.x * 0.02, tile.position.y * 0.02, game.surfaces[1].map_gen_settings.seed) * 16)
|
||||
if tile.position.x > -160 + noise then
|
||||
surface.set_tiles({{name = get_replacement_tile(surface, tile.position), position = {tile.position.x, tile.position.y}}}, true)
|
||||
end
|
||||
end
|
||||
|
||||
for _, entity in pairs(surface.find_entities_filtered({type = {'resource', 'cliff'}, area = {{-300, -256}, {300, 300}}})) do
|
||||
if entity.position.x > -300 + math_abs(simplex_noise(entity.position.x * 0.02, entity.position.y * 0.02, game.surfaces[1].map_gen_settings.seed) * 32) then
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local decorative_names = {}
|
||||
for k, v in pairs(game.decorative_prototypes) do
|
||||
if v.autoplace_specification then
|
||||
decorative_names[#decorative_names + 1] = k
|
||||
end
|
||||
end
|
||||
for x = -4, 4, 1 do
|
||||
for y = -3, 3, 1 do
|
||||
surface.regenerate_decorative(decorative_names, {{x, y}})
|
||||
end
|
||||
end
|
||||
|
||||
local _y = 80
|
||||
local ore_positions = {
|
||||
{x = spawn_position_x - 52, y = _y},
|
||||
{x = spawn_position_x - 52, y = _y * 0.5},
|
||||
{x = spawn_position_x - 52, y = 0},
|
||||
{x = spawn_position_x - 52, y = _y * -0.5},
|
||||
{x = spawn_position_x - 52, y = _y * -1}
|
||||
}
|
||||
shuffle(ore_positions)
|
||||
map_functions.draw_smoothed_out_ore_circle(ore_positions[1], 'copper-ore', surface, 15, 2500)
|
||||
map_functions.draw_smoothed_out_ore_circle(ore_positions[2], 'iron-ore', surface, 15, 2500)
|
||||
map_functions.draw_smoothed_out_ore_circle(ore_positions[3], 'coal', surface, 15, 1500)
|
||||
map_functions.draw_smoothed_out_ore_circle(ore_positions[4], 'stone', surface, 15, 1500)
|
||||
map_functions.draw_noise_tile_circle({x = spawn_position_x - 20, y = 0}, 'water', surface, 16)
|
||||
map_functions.draw_oil_circle(ore_positions[5], 'crude-oil', surface, 8, 200000)
|
||||
|
||||
local pos = surface.find_non_colliding_position('market', {spawn_position_x, 0}, 50, 1)
|
||||
local market = FDT.set('market', place_fish_market(surface, pos))
|
||||
|
||||
local r = 16
|
||||
for _, entity in pairs(
|
||||
surface.find_entities_filtered(
|
||||
{
|
||||
area = {
|
||||
{market.position.x - r, market.position.y - r},
|
||||
{market.position.x + r, market.position.y + r}
|
||||
},
|
||||
type = 'tree'
|
||||
}
|
||||
)
|
||||
) do
|
||||
local distance_to_center = math_sqrt((entity.position.x - market.position.x) ^ 2 + (entity.position.y - market.position.y) ^ 2)
|
||||
if distance_to_center < r then
|
||||
if math_random(1, r) > distance_to_center then
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local turret_pos = surface.find_non_colliding_position('gun-turret', {spawn_position_x + 5, 1}, 50, 1)
|
||||
local turret = surface.create_entity({name = 'gun-turret', position = turret_pos, force = 'player'})
|
||||
turret.insert({name = 'firearm-magazine', count = 32})
|
||||
|
||||
for x = -20, 20, 1 do
|
||||
for y = -20, 20, 1 do
|
||||
local market_pos = {x = market.position.x + x, y = market.position.y + y}
|
||||
local distance_to_center = x ^ 2 + y ^ 2
|
||||
if distance_to_center > 64 and distance_to_center < 225 then
|
||||
if math_random(1, 3) == 1 and surface.can_place_entity({name = 'wooden-chest', position = market_pos, force = 'player'}) then
|
||||
surface.create_entity({name = 'wooden-chest', position = market_pos, force = 'player'})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local area = {{x = -160, y = -96}, {x = 160, y = 96}}
|
||||
for _, tile in pairs(surface.find_tiles_filtered({name = 'water', area = area})) do
|
||||
if math_random(1, 32) == 1 then
|
||||
surface.create_entity({name = 'fish', position = tile.position})
|
||||
end
|
||||
end
|
||||
|
||||
local character_pos = surface.find_non_colliding_position('character', {spawn_position_x + 1, 4}, 50, 1)
|
||||
game.forces['player'].set_spawn_position(character_pos, surface)
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local spawn_pos = surface.find_non_colliding_position('character', {spawn_position_x + 1, 4}, 50, 1)
|
||||
player.teleport(spawn_pos, surface)
|
||||
end
|
||||
|
||||
local rr = 200
|
||||
local p = {x = -131, y = 5}
|
||||
game.forces.player.chart(
|
||||
surface,
|
||||
{
|
||||
{p.x - rr - 100, p.y - rr},
|
||||
{p.x + rr + 400, p.y + rr}
|
||||
}
|
||||
)
|
||||
|
||||
FDT.set('spawn_area_generated', true)
|
||||
end
|
||||
|
||||
local function process_chunk(left_top)
|
||||
local active_surface_index = FDT.get('active_surface_index')
|
||||
local surface = game.surfaces[active_surface_index]
|
||||
if not surface or not surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
generate_spawn_area(surface, left_top)
|
||||
enemy_territory(surface, left_top)
|
||||
fish_mouth(surface, left_top)
|
||||
|
||||
local market = FDT.get('market')
|
||||
|
||||
game.forces.player.chart(surface, {{left_top.x, left_top.y}, {left_top.x + 31, left_top.y + 31}})
|
||||
if market and market.valid then
|
||||
FDT.set('game_reset', false)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_chunk_generated(event)
|
||||
local map_name = 'pidgeotto'
|
||||
|
||||
if string.sub(event.surface.name, 0, #map_name) ~= map_name then
|
||||
return
|
||||
end
|
||||
|
||||
if FDT.get('stop_generating_map') then
|
||||
return
|
||||
end
|
||||
|
||||
local left_top = event.area.left_top
|
||||
Builder.make_chunk(event)
|
||||
|
||||
process_chunk(left_top)
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
|
||||
@@ -0,0 +1,61 @@
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
|
||||
local radius = 20
|
||||
|
||||
local whitelist = {
|
||||
['defender'] = 'explosive-cannon-projectile',
|
||||
['distractor'] = 'explosive-uranium-cannon-projectile',
|
||||
['destroyer'] = 'explosive-uranium-cannon-projectile'
|
||||
}
|
||||
|
||||
local function on_entity_died(event)
|
||||
local trapped_capsules_unlocked = FDT.get('trapped_capsules_unlocked')
|
||||
if not trapped_capsules_unlocked then
|
||||
return
|
||||
end
|
||||
|
||||
if not event.entity.valid then
|
||||
return
|
||||
end
|
||||
if not whitelist[event.entity.name] then
|
||||
return
|
||||
end
|
||||
|
||||
local valid_targets = {}
|
||||
local position = event.entity.position
|
||||
|
||||
for _, e in pairs(
|
||||
event.entity.surface.find_entities_filtered(
|
||||
{
|
||||
area = {{position.x - radius, position.y - radius}, {position.x + radius, position.y + radius}},
|
||||
force = 'enemy'
|
||||
}
|
||||
)
|
||||
) do
|
||||
if e.health then
|
||||
local distance_from_center = math.sqrt((e.position.x - position.x) ^ 2 + (e.position.y - position.y) ^ 2)
|
||||
if distance_from_center <= radius then
|
||||
valid_targets[#valid_targets + 1] = e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not valid_targets[1] then
|
||||
return
|
||||
end
|
||||
|
||||
event.entity.surface.create_entity(
|
||||
{
|
||||
name = whitelist[event.entity.name],
|
||||
position = position,
|
||||
force = 'player',
|
||||
source = position,
|
||||
target = valid_targets[math.random(1, #valid_targets)].position,
|
||||
max_range = 20,
|
||||
speed = 0.1
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_entity_died, on_entity_died)
|
||||
@@ -0,0 +1,51 @@
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
local radius = 8
|
||||
|
||||
local function damage_entities_around_target(entity, damage)
|
||||
for _, e in pairs(
|
||||
entity.surface.find_entities_filtered(
|
||||
{
|
||||
area = {
|
||||
{entity.position.x - radius, entity.position.y - radius},
|
||||
{entity.position.x + radius, entity.position.y + radius}
|
||||
}
|
||||
}
|
||||
)
|
||||
) do
|
||||
if e.health then
|
||||
if e.force.name ~= 'player' then
|
||||
local distance_from_center = math.sqrt((e.position.x - entity.position.x) ^ 2 + (e.position.y - entity.position.y) ^ 2)
|
||||
if distance_from_center <= radius then
|
||||
e.damage(damage, 'player', 'explosion')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_entity_died(event)
|
||||
local ultra_mines_unlocked = FDT.get('ultra_mines_unlocked')
|
||||
if not ultra_mines_unlocked then
|
||||
return
|
||||
end
|
||||
if not event.entity.valid then
|
||||
return
|
||||
end
|
||||
if event.entity.name ~= 'land-mine' then
|
||||
return
|
||||
end
|
||||
|
||||
event.entity.surface.create_entity(
|
||||
{
|
||||
name = 'big-artillery-explosion',
|
||||
position = event.entity.position
|
||||
}
|
||||
)
|
||||
|
||||
local damage = (1 + event.entity.force.get_ammo_damage_modifier('grenade')) * 250
|
||||
|
||||
damage_entities_around_target(event.entity, damage)
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_entity_died, on_entity_died)
|
||||
@@ -0,0 +1,29 @@
|
||||
local Event = require 'utils.event'
|
||||
local FDT = require 'maps.pidgeotto.table'
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
local vehicle_nanobots_unlocked = FDT.get('vehicle_nanobots_unlocked')
|
||||
|
||||
if not vehicle_nanobots_unlocked then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
if not player.character then
|
||||
return
|
||||
end
|
||||
if not player.character.driving then
|
||||
return
|
||||
end
|
||||
if not player.vehicle then
|
||||
return
|
||||
end
|
||||
if not player.vehicle.valid then
|
||||
return
|
||||
end
|
||||
if player.vehicle.health == player.vehicle.prototype.max_health then
|
||||
return
|
||||
end
|
||||
player.vehicle.health = player.vehicle.health + player.vehicle.prototype.max_health * 0.005
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
Reference in New Issue
Block a user