1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-03-03 14:53:01 +02:00

Merge Space Race into Code Base :D

Space Race is still very much a [WIP] and should be treated as such. Many features need to be added, but it is being merged in its current state to allow for easier internal integration. The map is in a playable state, and includes a configuration file. 

A list of future ideas and features to implement can be found at #996 and it should be notes that this is still a "high priority" project.
This commit is contained in:
theorangeangle 2020-03-01 23:34:23 -06:00 committed by GitHub
commit 092f30cded
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 3953 additions and 18 deletions

View File

@ -349,6 +349,7 @@ stds.factorio_control = {
"get_entity_by_tag",
"get_map_exchange_string",
"get_player",
"get_surface",
"help",
"is_demo",
"is_multiplayer",

View File

@ -154,7 +154,7 @@ if config.redmew_settings.enabled then
require 'features.gui.redmew_settings'
end
require 'features.snake.control'
--require 'features.snake.control'
-- Debug-only modules
if _DEBUG then

View File

@ -48,14 +48,20 @@ local function player_created(event)
gui.top.style = 'slot_table_spacing_horizontal_flow'
gui.left.style = 'slot_table_spacing_vertical_flow'
if not config.cutscene then
Public.show_start_up(player)
end
local character = player.character
if not character or not character.valid then
return
end
local player_insert = player.insert
for _, item in pairs(config.starting_items) do
player_insert(item)
end
if not config.cutscene then
Public.show_start_up(player)
end
end
Event.add(defines.events.on_player_created, player_created)
@ -89,6 +95,20 @@ if _CHEATS then
player.cheat_mode = true
local cheats = config.cheats
if not memory.forces_initialized[force.name] then
force.manual_mining_speed_modifier = cheats.manual_mining_speed_modifier
force.character_inventory_slots_bonus = cheats.character_inventory_slots_bonus
force.character_running_speed_modifier = cheats.character_running_speed_modifier
force.character_health_bonus = cheats.character_health_bonus
end
memory.forces_initialized[force.name] = true
local character = player.character
if not character or not character.valid then
return
end
local player_insert = player.insert
if cheats.start_with_power_armor then
@ -114,15 +134,6 @@ if _CHEATS then
for _, item in pairs(cheats.starting_items) do
player_insert(item)
end
if not memory.forces_initialized[force.name] then
force.manual_mining_speed_modifier = cheats.manual_mining_speed_modifier
force.character_inventory_slots_bonus = cheats.character_inventory_slots_bonus
force.character_running_speed_modifier = cheats.character_running_speed_modifier
force.character_health_bonus = cheats.character_health_bonus
end
memory.forces_initialized[force.name] = true
end
Event.add(defines.events.on_player_created, player_created_cheat_mode)

View File

@ -289,7 +289,7 @@ local function make_board()
if x == 0 or x == size or y == 0 or y == size then
tile_name = 'deepwater'
elseif x % 2 == 1 and y % 2 == 1 then
tile_name = 'grass-1'
tile_name = 'landfill'
else
tile_name = 'water'
end

View File

@ -34,7 +34,7 @@ entity_built_callback =
if entity.health == 0 then
entity.active = true
entity.die('enemy')
entity.die('neutral')
return
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -0,0 +1,409 @@
return {
height = 403,
width = 339,
data = {
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,159,2,20,1,160,},
{1,150,2,38,1,151,},
{1,142,2,54,1,143,},
{1,136,2,66,1,137,},
{1,132,2,73,1,134,},
{1,128,2,82,1,129,},
{1,125,2,89,1,125,},
{1,122,2,95,1,122,},
{1,118,2,101,1,120,},
{1,115,2,107,1,117,},
{1,112,2,114,1,113,},
{1,110,2,118,1,111,},
{1,107,2,124,1,108,},
{1,105,2,128,1,106,},
{1,103,2,131,1,105,},
{1,101,2,136,1,102,},
{1,99,2,140,1,100,},
{1,97,2,144,1,98,},
{1,95,2,148,1,96,},
{1,93,2,152,1,94,},
{1,92,2,155,1,92,},
{1,90,2,158,1,91,},
{1,88,2,162,1,89,},
{1,86,2,166,1,87,},
{1,85,2,169,1,85,},
{1,83,2,172,1,84,},
{1,82,2,175,1,82,},
{1,80,2,178,1,81,},
{1,78,2,181,1,80,},
{1,77,2,184,1,78,},
{1,75,2,187,1,77,},
{1,74,2,190,1,75,},
{1,73,2,192,1,74,},
{1,71,2,196,1,72,},
{1,70,2,198,1,71,},
{1,69,2,200,1,70,},
{1,68,2,202,1,69,},
{1,66,2,205,1,68,},
{1,65,2,207,1,67,},
{1,64,2,210,1,65,},
{1,63,2,212,1,64,},
{1,62,2,214,1,63,},
{1,61,2,216,1,62,},
{1,60,2,218,1,61,},
{1,59,2,220,1,60,},
{1,58,2,222,1,59,},
{1,57,2,224,1,58,},
{1,56,2,226,1,57,},
{1,55,2,228,1,56,},
{1,54,2,230,1,55,},
{1,53,2,232,1,54,},
{1,52,2,234,1,53,},
{1,51,2,236,1,52,},
{1,50,2,238,1,51,},
{1,49,2,240,1,50,},
{1,48,2,242,1,49,},
{1,47,2,243,1,49,},
{1,47,2,244,1,48,},
{1,46,2,246,1,47,},
{1,45,2,248,1,46,},
{1,44,2,250,1,45,},
{1,43,2,252,1,44,},
{1,43,2,252,1,44,},
{1,42,2,254,1,43,},
{1,41,2,256,1,42,},
{1,40,2,258,1,41,},
{1,40,2,258,1,41,},
{1,39,2,260,1,40,},
{1,38,2,261,1,40,},
{1,38,2,262,1,39,},
{1,37,2,264,1,38,},
{1,36,2,266,1,37,},
{1,36,2,266,1,37,},
{1,35,2,268,1,36,},
{1,35,2,269,1,35,},
{1,34,2,270,1,35,},
{1,33,2,272,1,34,},
{1,33,2,273,1,33,},
{1,32,2,274,1,33,},
{1,32,2,275,1,32,},
{1,31,2,276,1,32,},
{1,30,2,278,1,31,},
{1,30,2,278,1,31,},
{1,29,2,280,1,30,},
{1,28,2,282,1,29,},
{1,28,2,282,1,29,},
{1,27,2,284,1,28,},
{1,27,2,284,1,28,},
{1,26,2,286,1,27,},
{1,26,2,286,1,27,},
{1,25,2,288,1,26,},
{1,25,2,288,1,26,},
{1,24,2,290,1,25,},
{1,24,2,290,1,25,},
{1,24,2,290,1,25,},
{1,23,2,292,1,24,},
{1,23,2,292,1,24,},
{1,22,2,294,1,23,},
{1,22,2,294,1,23,},
{1,21,2,296,1,22,},
{1,21,2,296,1,22,},
{1,21,2,296,1,22,},
{1,20,2,298,1,21,},
{1,20,2,298,1,21,},
{1,19,2,300,1,20,},
{1,19,2,300,1,20,},
{1,19,2,300,1,20,},
{1,18,2,301,1,20,},
{1,18,2,302,1,19,},
{1,18,2,302,1,19,},
{1,18,2,302,1,19,},
{1,17,2,304,1,18,},
{1,17,2,304,1,18,},
{1,17,2,305,1,17,},
{1,16,2,306,1,17,},
{1,16,2,306,1,17,},
{1,16,2,306,1,17,},
{1,15,2,308,1,16,},
{1,15,2,308,1,16,},
{1,15,2,308,1,16,},
{1,15,2,308,1,16,},
{1,14,2,310,1,15,},
{1,14,2,310,1,15,},
{1,14,2,310,1,15,},
{1,14,2,310,1,15,},
{1,13,2,311,1,15,},
{1,13,2,312,1,14,},
{1,13,2,312,1,14,},
{1,13,2,312,1,14,},
{1,13,2,312,1,14,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,315,1,12,},
{1,12,2,315,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,10,2,318,1,11,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,316,1,12,},
{1,11,2,315,1,13,},
{1,11,2,315,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,12,2,314,1,13,},
{1,13,2,312,1,14,},
{1,13,2,312,1,14,},
{1,13,2,312,1,14,},
{1,13,2,312,1,14,},
{1,13,2,312,1,14,},
{1,14,2,310,1,15,},
{1,14,2,89,1,15,2,102,1,16,2,88,1,15,},
{1,14,2,86,1,21,2,95,1,22,2,86,1,15,},
{1,15,2,82,1,27,2,89,1,28,2,83,1,15,},
{1,15,2,80,1,31,2,85,1,32,2,80,1,16,},
{1,15,2,77,1,37,2,80,1,36,2,78,1,16,},
{1,15,2,76,1,39,2,78,1,39,2,76,1,16,},
{1,15,2,74,1,42,2,75,1,43,2,74,1,16,},
{1,16,2,72,1,44,2,73,1,45,2,72,1,17,},
{1,16,2,71,1,47,2,70,1,47,2,71,1,17,},
{1,16,2,70,1,49,2,68,1,49,2,70,1,17,},
{1,17,2,68,1,51,2,66,1,51,2,68,1,18,},
{1,17,2,67,1,53,2,64,1,53,2,67,1,18,},
{1,17,2,66,1,55,2,62,1,54,2,67,1,18,},
{1,17,2,65,1,56,2,61,1,56,2,65,1,19,},
{1,18,2,64,1,57,2,60,1,57,2,64,1,19,},
{1,18,2,63,1,59,2,58,1,59,2,63,1,19,},
{1,19,2,61,1,61,2,56,1,61,2,61,1,20,},
{1,19,2,61,1,61,2,56,1,61,2,61,1,20,},
{1,19,2,60,1,63,2,54,1,63,2,60,1,20,},
{1,20,2,59,1,63,2,54,1,63,2,59,1,21,},
{1,20,2,58,1,65,2,52,1,65,2,58,1,21,},
{1,20,2,58,1,65,2,52,1,65,2,58,1,21,},
{1,21,2,57,1,65,2,51,1,66,2,57,1,22,},
{1,21,2,56,1,67,2,50,1,67,2,56,1,22,},
{1,21,2,56,1,67,2,50,1,67,2,56,1,22,},
{1,22,2,55,1,67,2,49,1,68,2,55,1,23,},
{1,22,2,54,1,69,2,48,1,69,2,54,1,23,},
{1,23,2,53,1,69,2,48,1,69,2,53,1,24,},
{1,23,2,53,1,69,2,48,1,69,2,53,1,24,},
{1,24,2,52,1,70,2,47,1,69,2,52,1,25,},
{1,24,2,52,1,70,2,46,1,71,2,51,1,25,},
{1,25,2,50,1,71,2,46,1,71,2,50,1,26,},
{1,25,2,50,1,71,2,46,1,71,2,50,1,26,},
{1,25,2,50,1,71,2,46,1,71,2,50,1,26,},
{1,26,2,49,1,71,2,46,1,71,2,49,1,27,},
{1,26,2,49,1,71,2,46,1,71,2,49,1,27,},
{1,27,2,48,1,71,2,46,1,71,2,48,1,28,},
{1,27,2,48,1,71,2,46,1,71,2,48,1,28,},
{1,28,2,47,1,71,2,46,1,71,2,47,1,29,},
{1,29,2,46,1,71,2,46,1,70,2,47,1,30,},
{1,29,2,46,1,70,2,47,1,70,2,47,1,30,},
{1,30,2,46,1,69,2,48,1,69,2,46,1,31,},
{1,31,2,45,1,69,2,48,1,69,2,46,1,31,},
{1,31,2,45,1,69,2,48,1,69,2,45,1,32,},
{1,32,2,45,1,68,2,48,1,68,2,46,1,32,},
{1,32,2,45,1,67,2,50,1,67,2,45,1,33,},
{1,33,2,44,1,67,2,50,1,67,2,44,1,34,},
{1,33,2,45,1,66,2,50,1,66,2,45,1,34,},
{1,34,2,44,1,65,2,52,1,65,2,44,1,35,},
{1,34,2,44,1,65,2,52,1,65,2,43,1,36,},
{1,35,2,44,1,64,2,53,1,63,2,44,1,36,},
{1,36,2,43,1,63,2,54,1,63,2,43,1,37,},
{1,36,2,44,1,61,2,56,1,61,2,44,1,37,},
{1,37,2,43,1,61,2,56,1,60,2,45,1,37,},
{1,38,2,43,1,59,2,58,1,59,2,45,1,37,},
{1,39,2,42,1,59,2,58,1,58,2,46,1,37,},
{1,39,2,44,1,56,2,60,1,56,2,47,1,37,},
{1,40,2,43,1,55,2,62,1,55,2,47,1,37,},
{1,40,2,44,1,53,2,64,1,53,2,48,1,37,},
{1,40,2,45,1,51,2,66,1,51,2,49,1,37,},
{1,40,2,46,1,49,2,68,1,49,2,50,1,37,},
{1,40,2,47,1,47,2,70,1,47,2,51,1,37,},
{1,40,2,48,1,45,2,72,1,45,2,52,1,37,},
{1,40,2,49,1,43,2,75,1,41,2,54,1,37,},
{1,40,2,51,1,39,2,78,1,39,2,55,1,37,},
{1,40,2,53,1,36,2,80,1,36,2,57,1,37,},
{1,40,2,55,1,32,2,84,1,32,2,59,1,37,},
{1,40,2,57,1,28,2,89,1,27,2,61,1,37,},
{1,40,2,59,1,23,2,94,1,23,2,63,1,37,},
{1,40,2,63,1,15,2,102,1,15,2,67,1,37,},
{1,40,2,185,1,2,2,75,1,37,},
{1,40,2,262,1,37,},
{1,40,2,262,1,37,},
{1,40,2,262,1,37,},
{1,40,2,262,1,37,},
{1,40,2,262,1,37,},
{1,40,2,262,1,37,},
{1,40,2,262,1,37,},
{1,40,2,128,1,7,2,127,1,37,},
{1,40,2,125,1,12,2,125,1,37,},
{1,40,2,124,1,14,2,124,1,37,},
{1,40,2,123,1,16,2,123,1,37,},
{1,40,2,122,1,18,2,122,1,37,},
{1,40,2,121,1,20,2,121,1,37,},
{1,40,2,120,1,22,2,120,1,37,},
{1,40,2,119,1,24,2,119,1,37,},
{1,40,2,118,1,26,2,118,1,37,},
{1,40,2,117,1,28,2,117,1,37,},
{1,40,2,116,1,30,2,116,1,37,},
{1,40,2,115,1,32,2,115,1,37,},
{1,40,2,114,1,34,2,114,1,37,},
{1,40,2,113,1,36,2,113,1,37,},
{1,40,2,112,1,38,2,112,1,37,},
{1,40,2,111,1,40,2,111,1,37,},
{1,40,2,110,1,42,2,110,1,37,},
{1,40,2,109,1,44,2,109,1,37,},
{1,40,2,108,1,46,2,108,1,37,},
{1,40,2,107,1,48,2,107,1,37,},
{1,40,2,106,1,50,2,106,1,37,},
{1,40,2,105,1,52,2,105,1,37,},
{1,40,2,104,1,54,2,103,1,38,},
{1,40,2,103,1,55,2,103,1,38,},
{1,40,2,102,1,57,2,102,1,38,},
{1,40,2,102,1,58,2,101,1,38,},
{1,40,2,101,1,60,2,100,1,38,},
{1,41,2,100,1,60,2,100,1,38,},
{1,41,2,99,1,61,2,99,1,39,},
{1,41,2,100,1,60,2,99,1,39,},
{1,41,2,100,1,60,2,99,1,39,},
{1,42,2,101,1,56,2,100,1,40,},
{1,42,2,257,1,40,},
{1,43,2,256,1,40,},
{1,43,2,255,1,41,},
{1,44,2,254,1,41,},
{1,44,2,253,1,42,},
{1,44,2,253,1,42,},
{1,45,2,251,1,43,},
{1,45,2,250,1,44,},
{1,46,2,248,1,45,},
{1,47,2,246,1,46,},
{1,48,2,245,1,46,},
{1,49,2,243,1,47,},
{1,50,2,241,1,48,},
{1,51,2,238,1,50,},
{1,52,2,236,1,51,},
{1,53,2,234,1,52,},
{1,55,2,230,1,54,},
{1,57,2,226,1,56,},
{1,60,2,220,1,59,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,158,1,91,},
{1,90,2,157,1,92,},
{1,91,2,156,1,92,},
{1,91,2,156,1,92,},
{1,91,2,156,1,92,},
{1,91,2,38,1,1,2,38,1,2,2,37,1,2,2,38,1,92,},
{1,92,2,37,1,2,2,37,1,2,2,37,1,2,2,37,1,93,},
{1,92,2,36,1,3,2,37,1,2,2,37,1,2,2,37,1,93,},
{1,93,2,35,1,4,2,35,1,4,2,35,1,4,2,35,1,94,},
{1,94,2,33,1,6,2,33,1,6,2,34,1,5,2,34,1,94,},
{1,94,2,33,1,6,2,33,1,7,2,32,1,7,2,32,1,95,},
{1,95,2,31,1,8,2,31,1,8,2,31,1,8,2,31,1,96,},
{1,96,2,29,1,10,2,29,1,10,2,29,1,10,2,29,1,97,},
{1,97,2,27,1,12,2,27,1,12,2,27,1,12,2,27,1,98,},
{1,98,2,25,1,14,2,25,1,14,2,25,1,14,2,25,1,99,},
{1,99,2,23,1,16,2,23,1,16,2,23,1,16,2,23,1,100,},
{1,101,2,19,1,20,2,19,1,20,2,19,1,20,2,19,1,102,},
{1,104,2,14,1,24,2,15,1,24,2,15,1,24,2,15,1,104,},
{1,107,2,7,1,33,2,6,1,33,2,6,1,33,2,6,1,108,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
{1,339,},
}
}

View File

@ -0,0 +1,677 @@
return {
height = 671,
width = 667,
data = {
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,177,2,39,1,232,2,40,1,179,},
{1,169,2,54,1,218,2,54,1,172,},
{1,163,2,66,1,206,2,66,1,166,},
{1,158,2,76,1,195,2,77,1,161,},
{1,154,2,85,1,186,2,86,1,156,},
{1,150,2,93,1,178,2,93,1,153,},
{1,146,2,100,1,172,2,100,1,149,},
{1,143,2,107,1,165,2,106,1,146,},
{1,140,2,113,1,158,2,113,1,143,},
{1,137,2,119,1,152,2,119,1,140,},
{1,134,2,124,1,148,2,124,1,137,},
{1,131,2,130,1,142,2,130,1,134,},
{1,128,2,136,1,136,2,136,1,131,},
{1,126,2,140,1,132,2,140,1,129,},
{1,124,2,144,1,128,2,144,1,127,},
{1,122,2,148,1,124,2,148,1,125,},
{1,120,2,152,1,120,2,152,1,123,},
{1,117,2,158,1,114,2,158,1,120,},
{1,115,2,162,1,110,2,162,1,118,},
{1,113,2,166,1,106,2,166,1,116,},
{1,111,2,169,1,103,2,170,1,114,},
{1,109,2,173,1,99,2,174,1,112,},
{1,107,2,177,1,96,2,177,1,110,},
{1,106,2,180,1,92,2,180,1,109,},
{1,104,2,184,1,88,2,184,1,107,},
{1,103,2,186,1,86,2,187,1,105,},
{1,101,2,190,1,82,2,191,1,103,},
{1,99,2,194,1,79,2,193,1,102,},
{1,98,2,196,1,76,2,197,1,100,},
{1,96,2,200,1,72,2,200,1,99,},
{1,94,2,203,1,70,2,203,1,97,},
{1,93,2,206,1,66,2,206,1,96,},
{1,91,2,209,1,64,2,209,1,94,},
{1,90,2,212,1,61,2,211,1,93,},
{1,88,2,215,1,58,2,215,1,91,},
{1,87,2,217,1,56,2,217,1,90,},
{1,86,2,220,1,53,2,219,1,89,},
{1,85,2,222,1,50,2,222,1,88,},
{1,83,2,225,1,48,2,225,1,86,},
{1,82,2,227,1,46,2,227,1,85,},
{1,81,2,230,1,43,2,229,1,84,},
{1,80,2,232,1,40,2,232,1,83,},
{1,78,2,235,1,38,2,235,1,81,},
{1,77,2,237,1,36,2,237,1,80,},
{1,76,2,239,1,34,2,239,1,79,},
{1,75,2,242,1,30,2,242,1,78,},
{1,73,2,245,1,28,2,245,1,76,},
{1,72,2,247,1,26,2,247,1,75,},
{1,72,2,248,1,24,2,248,1,75,},
{1,71,2,250,1,22,2,251,1,73,},
{1,69,2,253,1,20,2,253,1,72,},
{1,68,2,255,1,18,2,255,1,71,},
{1,67,2,257,1,16,2,257,1,70,},
{1,66,2,259,1,14,2,259,1,69,},
{1,65,2,261,1,12,2,261,1,68,},
{1,64,2,263,1,10,2,263,1,67,},
{1,64,2,264,1,8,2,264,1,67,},
{1,63,2,266,1,6,2,266,1,66,},
{1,61,2,269,1,4,2,268,1,65,},
{1,60,2,271,1,2,2,271,1,63,},
{1,59,2,545,1,63,},
{1,59,2,546,1,62,},
{1,58,2,548,1,61,},
{1,57,2,550,1,60,},
{1,56,2,552,1,59,},
{1,55,2,554,1,58,},
{1,55,2,555,1,57,},
{1,54,2,556,1,57,},
{1,53,2,558,1,56,},
{1,52,2,560,1,55,},
{1,51,2,562,1,54,},
{1,51,2,562,1,54,},
{1,50,2,564,1,53,},
{1,49,2,566,1,52,},
{1,48,2,568,1,51,},
{1,47,2,570,1,50,},
{1,47,2,570,1,50,},
{1,46,2,572,1,49,},
{1,45,2,574,1,48,},
{1,45,2,575,1,47,},
{1,44,2,576,1,47,},
{1,43,2,578,1,46,},
{1,43,2,578,1,46,},
{1,42,2,580,1,45,},
{1,41,2,582,1,44,},
{1,41,2,582,1,44,},
{1,40,2,584,1,43,},
{1,40,2,585,1,42,},
{1,39,2,586,1,42,},
{1,38,2,588,1,41,},
{1,38,2,588,1,41,},
{1,37,2,590,1,40,},
{1,36,2,591,1,40,},
{1,36,2,592,1,39,},
{1,35,2,594,1,38,},
{1,35,2,594,1,38,},
{1,34,2,186,1,1,2,409,1,37,},
{1,34,2,186,1,2,2,408,1,37,},
{1,33,2,186,1,3,2,409,1,36,},
{1,33,2,186,1,3,2,409,1,36,},
{1,32,2,186,1,5,2,409,1,35,},
{1,32,2,186,1,5,2,409,1,35,},
{1,31,2,187,1,5,2,410,1,34,},
{1,31,2,186,1,7,2,409,1,34,},
{1,30,2,187,1,7,2,410,1,33,},
{1,30,2,186,1,8,2,410,1,33,},
{1,30,2,186,1,9,2,409,1,33,},
{1,29,2,186,1,10,2,410,1,32,},
{1,29,2,186,1,11,2,409,1,32,},
{1,28,2,187,1,11,2,410,1,31,},
{1,28,2,186,1,12,2,410,1,31,},
{1,27,2,187,1,12,2,411,1,30,},
{1,27,2,186,1,14,2,410,1,30,},
{1,26,2,187,1,14,2,410,1,30,},
{1,26,2,186,1,15,2,411,1,29,},
{1,26,2,186,1,16,2,410,1,29,},
{1,25,2,187,1,16,2,411,1,28,},
{1,25,2,186,1,17,2,411,1,28,},
{1,24,2,187,1,18,2,410,1,28,},
{1,24,2,186,1,19,2,411,1,27,},
{1,24,2,186,1,20,2,410,1,27,},
{1,23,2,186,1,21,2,411,1,26,},
{1,23,2,186,1,21,2,411,1,26,},
{1,23,2,186,1,21,2,411,1,26,},
{1,22,2,186,1,23,2,411,1,25,},
{1,22,2,186,1,23,2,411,1,25,},
{1,22,2,185,1,25,2,410,1,25,},
{1,22,2,185,1,25,2,410,1,25,},
{1,21,2,185,1,26,2,411,1,24,},
{1,21,2,185,1,26,2,411,1,24,},
{1,21,2,184,1,28,2,410,1,24,},
{1,20,2,185,1,28,2,411,1,23,},
{1,20,2,185,1,29,2,410,1,23,},
{1,20,2,184,1,30,2,410,1,23,},
{1,19,2,185,1,30,2,411,1,22,},
{1,19,2,184,1,31,2,411,1,22,},
{1,19,2,184,1,32,2,410,1,22,},
{1,19,2,184,1,32,2,410,1,22,},
{1,18,2,184,1,33,2,411,1,21,},
{1,18,2,184,1,34,2,410,1,21,},
{1,18,2,183,1,35,2,410,1,21,},
{1,18,2,183,1,35,2,410,1,21,},
{1,17,2,183,1,37,2,410,1,20,},
{1,17,2,183,1,37,2,410,1,20,},
{1,17,2,183,1,37,2,410,1,20,},
{1,17,2,182,1,39,2,409,1,20,},
{1,17,2,182,1,39,2,409,1,20,},
{1,17,2,181,1,40,2,409,1,20,},
{1,16,2,182,1,41,2,409,1,19,},
{1,16,2,181,1,42,2,409,1,19,},
{1,16,2,181,1,42,2,409,1,19,},
{1,16,2,181,1,43,2,408,1,19,},
{1,16,2,180,1,44,2,408,1,19,},
{1,16,2,180,1,44,2,408,1,19,},
{1,15,2,180,1,46,2,408,1,18,},
{1,15,2,180,1,46,2,408,1,18,},
{1,15,2,179,1,47,2,408,1,18,},
{1,15,2,179,1,48,2,407,1,18,},
{1,15,2,179,1,48,2,407,1,18,},
{1,15,2,178,1,49,2,407,1,18,},
{1,15,2,178,1,50,2,406,1,18,},
{1,15,2,177,1,51,2,406,1,18,},
{1,14,2,178,1,51,2,407,1,17,},
{1,14,2,178,1,52,2,406,1,17,},
{1,14,2,177,1,53,2,406,1,17,},
{1,14,2,177,1,54,2,405,1,17,},
{1,14,2,176,1,55,2,405,1,17,},
{1,14,2,176,1,55,2,405,1,17,},
{1,14,2,175,1,57,2,404,1,17,},
{1,14,2,175,1,57,2,404,1,17,},
{1,14,2,174,1,58,2,404,1,17,},
{1,14,2,174,1,58,2,404,1,17,},
{1,14,2,174,1,59,2,403,1,17,},
{1,14,2,173,1,60,2,403,1,17,},
{1,14,2,173,1,61,2,402,1,17,},
{1,14,2,172,1,62,2,402,1,17,},
{1,14,2,172,1,62,2,402,1,17,},
{1,14,2,171,1,64,2,401,1,17,},
{1,14,2,171,1,64,2,402,1,16,},
{1,14,2,171,1,64,2,401,1,17,},
{1,14,2,170,1,65,2,401,1,17,},
{1,14,2,170,1,66,2,400,1,17,},
{1,14,2,169,1,67,2,400,1,17,},
{1,14,2,169,1,67,2,400,1,17,},
{1,14,2,168,1,69,2,399,1,17,},
{1,14,2,168,1,69,2,399,1,17,},
{1,14,2,168,1,69,2,399,1,17,},
{1,14,2,167,1,71,2,398,1,17,},
{1,14,2,167,1,71,2,398,1,17,},
{1,14,2,166,1,72,2,398,1,17,},
{1,14,2,166,1,73,2,397,1,17,},
{1,14,2,165,1,74,2,397,1,17,},
{1,14,2,165,1,75,2,396,1,17,},
{1,14,2,165,1,75,2,396,1,17,},
{1,14,2,164,1,76,2,396,1,17,},
{1,14,2,164,1,76,2,396,1,17,},
{1,14,2,163,1,78,2,395,1,17,},
{1,14,2,163,1,78,2,395,1,17,},
{1,14,2,162,1,79,2,395,1,17,},
{1,14,2,162,1,80,2,394,1,17,},
{1,14,2,162,1,80,2,394,1,17,},
{1,14,2,161,1,81,2,394,1,17,},
{1,14,2,161,1,82,2,393,1,17,},
{1,14,2,160,1,83,2,393,1,17,},
{1,14,2,160,1,84,2,392,1,17,},
{1,15,2,159,1,84,2,391,1,18,},
{1,15,2,158,1,85,2,391,1,18,},
{1,15,2,158,1,85,2,391,1,18,},
{1,15,2,157,1,87,2,390,1,18,},
{1,15,2,157,1,87,2,390,1,18,},
{1,15,2,156,1,89,2,389,1,18,},
{1,15,2,156,1,89,2,389,1,18,},
{1,15,2,155,1,90,2,389,1,18,},
{1,15,2,155,1,91,2,388,1,18,},
{1,16,2,154,1,91,2,387,1,19,},
{1,16,2,153,1,92,2,387,1,19,},
{1,16,2,153,1,93,2,386,1,19,},
{1,16,2,152,1,94,2,386,1,19,},
{1,16,2,152,1,94,2,386,1,19,},
{1,16,2,151,1,95,2,386,1,19,},
{1,17,2,150,1,96,2,385,1,19,},
{1,17,2,150,1,96,2,384,1,20,},
{1,17,2,149,1,98,2,383,1,20,},
{1,17,2,149,1,49,2,1,1,48,2,383,1,20,},
{1,17,2,148,1,50,2,1,1,48,2,383,1,20,},
{1,17,2,148,1,50,2,1,1,48,2,383,1,20,},
{1,17,2,148,1,49,2,3,1,48,2,382,1,20,},
{1,18,2,146,1,50,2,3,1,48,2,382,1,20,},
{1,18,2,146,1,49,2,5,1,48,2,380,1,21,},
{1,18,2,145,1,50,2,5,1,48,2,380,1,21,},
{1,18,2,145,1,49,2,6,1,48,2,380,1,21,},
{1,18,2,144,1,50,2,6,1,48,2,380,1,21,},
{1,18,2,144,1,49,2,8,1,48,2,379,1,21,},
{1,19,2,142,1,50,2,8,1,48,2,378,1,22,},
{1,19,2,142,1,50,2,8,1,48,2,378,1,22,},
{1,19,2,142,1,49,2,10,1,48,2,377,1,22,},
{1,19,2,141,1,50,2,10,1,48,2,377,1,22,},
{1,20,2,140,1,49,2,11,1,49,2,376,1,22,},
{1,20,2,139,1,50,2,12,1,48,2,375,1,23,},
{1,20,2,139,1,49,2,13,1,48,2,375,1,23,},
{1,20,2,138,1,50,2,14,1,47,2,375,1,23,},
{1,20,2,138,1,50,2,14,1,48,2,374,1,23,},
{1,21,2,137,1,49,2,15,1,48,2,373,1,24,},
{1,21,2,136,1,50,2,16,1,47,2,373,1,24,},
{1,21,2,136,1,49,2,17,1,48,2,372,1,24,},
{1,21,2,135,1,50,2,17,1,48,2,372,1,24,},
{1,22,2,134,1,50,2,18,1,47,2,372,1,24,},
{1,22,2,133,1,50,2,19,1,48,2,370,1,25,},
{1,22,2,133,1,50,2,19,1,48,2,370,1,25,},
{1,22,2,133,1,49,2,20,1,48,2,370,1,25,},
{1,23,2,131,1,50,2,21,1,48,2,369,1,25,},
{1,23,2,131,1,49,2,22,1,48,2,368,1,26,},
{1,23,2,130,1,50,2,22,1,48,2,368,1,26,},
{1,24,2,129,1,49,2,24,1,48,2,367,1,26,},
{1,24,2,128,1,50,2,24,1,48,2,366,1,27,},
{1,24,2,128,1,49,2,26,1,48,2,365,1,27,},
{1,24,2,128,1,49,2,26,1,48,2,365,1,27,},
{1,25,2,126,1,50,2,26,1,48,2,365,1,27,},
{1,25,2,126,1,49,2,28,1,48,2,363,1,28,},
{1,25,2,125,1,50,2,28,1,48,2,363,1,28,},
{1,26,2,124,1,49,2,29,1,48,2,363,1,28,},
{1,26,2,123,1,50,2,30,1,48,2,361,1,29,},
{1,26,2,123,1,50,2,30,1,48,2,361,1,29,},
{1,26,2,122,1,50,2,31,1,48,2,361,1,29,},
{1,27,2,121,1,50,2,32,1,48,2,359,1,30,},
{1,27,2,121,1,49,2,33,1,48,2,359,1,30,},
{1,27,2,120,1,50,2,33,1,48,2,359,1,30,},
{1,28,2,119,1,49,2,35,1,47,2,358,1,31,},
{1,28,2,118,1,50,2,35,1,48,2,357,1,31,},
{1,28,2,118,1,50,2,35,1,48,2,357,1,31,},
{1,29,2,117,1,49,2,36,1,48,2,357,1,31,},
{1,29,2,116,1,50,2,37,1,48,2,355,1,32,},
{1,29,2,116,1,49,2,38,1,48,2,355,1,32,},
{1,30,2,114,1,50,2,39,1,47,2,355,1,32,},
{1,30,2,114,1,49,2,40,1,48,2,353,1,33,},
{1,30,2,113,1,50,2,40,1,48,2,353,1,33,},
{1,31,2,112,1,49,2,42,1,47,2,352,1,34,},
{1,31,2,112,1,49,2,42,1,48,2,351,1,34,},
{1,32,2,110,1,50,2,42,1,48,2,351,1,34,},
{1,32,2,110,1,49,2,43,1,48,2,350,1,35,},
{1,32,2,109,1,50,2,44,1,48,2,349,1,35,},
{1,33,2,108,1,49,2,45,1,48,2,349,1,35,},
{1,33,2,107,1,50,2,45,1,49,2,347,1,36,},
{1,33,2,107,1,50,2,46,1,48,2,347,1,36,},
{1,34,2,106,1,49,2,47,1,48,2,346,1,37,},
{1,34,2,105,1,50,2,48,1,47,2,346,1,37,},
{1,35,2,104,1,49,2,49,1,48,2,345,1,37,},
{1,35,2,103,1,50,2,49,1,48,2,344,1,38,},
{1,36,2,102,1,49,2,51,1,47,2,344,1,38,},
{1,36,2,102,1,49,2,51,1,48,2,342,1,39,},
{1,36,2,101,1,50,2,51,1,48,2,342,1,39,},
{1,37,2,100,1,49,2,52,1,48,2,342,1,39,},
{1,37,2,99,1,50,2,53,1,48,2,340,1,40,},
{1,38,2,98,1,49,2,54,1,48,2,340,1,40,},
{1,38,2,98,1,49,2,55,1,47,2,340,1,40,},
{1,184,2,56,1,48,2,338,1,41,},
{1,184,2,56,1,48,2,337,1,42,},
{1,184,2,56,1,48,2,337,1,42,},
{1,183,2,58,1,48,2,336,1,42,},
{1,183,2,58,1,48,2,335,1,43,},
{1,182,2,60,1,48,2,334,1,43,},
{1,182,2,60,1,48,2,333,1,44,},
{1,181,2,61,1,48,2,333,1,44,},
{1,181,2,62,1,47,2,332,1,45,},
{1,180,2,63,1,48,2,331,1,45,},
{1,180,2,63,1,48,2,330,1,46,},
{1,180,2,64,1,48,2,329,1,46,},
{1,179,2,65,1,48,2,328,1,47,},
{1,179,2,65,1,48,2,328,1,47,},
{1,178,2,67,1,48,2,326,1,48,},
{1,178,2,67,1,48,2,326,1,48,},
{1,178,2,67,1,48,2,326,1,48,},
{1,177,2,69,1,48,2,324,1,49,},
{1,177,2,69,1,48,2,324,1,49,},
{1,176,2,70,1,48,2,323,1,50,},
{1,176,2,70,1,48,2,323,1,50,},
{1,175,2,72,1,48,2,321,1,51,},
{1,175,2,72,1,48,2,321,1,51,},
{1,175,2,73,1,47,2,121,1,14,2,185,1,52,},
{1,174,2,74,1,48,2,116,1,22,2,181,1,52,},
{1,174,2,74,1,48,2,112,1,30,2,176,1,53,},
{1,173,2,75,1,48,2,110,1,34,2,174,1,53,},
{1,173,2,76,1,48,2,107,1,39,2,170,1,54,},
{1,172,2,77,1,48,2,104,1,44,2,167,1,55,},
{1,172,2,78,1,47,2,103,1,46,2,166,1,55,},
{1,171,2,79,1,48,2,100,1,50,2,163,1,56,},
{1,171,2,79,1,48,2,99,1,53,2,161,1,56,},
{1,171,2,79,1,48,2,97,1,56,2,159,1,57,},
{1,170,2,81,1,48,2,95,1,58,2,158,1,57,},
{1,170,2,81,1,48,2,94,1,60,2,156,1,58,},
{1,169,2,83,1,47,2,93,1,62,2,155,1,58,},
{1,169,2,83,1,48,2,91,1,64,2,153,1,59,},
{1,169,2,83,1,48,2,90,1,66,2,152,1,59,},
{1,168,2,85,1,47,2,89,1,68,2,150,1,60,},
{1,168,2,85,1,48,2,87,1,70,2,149,1,60,},
{1,167,2,86,1,48,2,86,1,72,2,147,1,61,},
{1,167,2,87,1,47,2,86,1,73,2,145,1,62,},
{1,166,2,88,1,48,2,84,1,74,2,145,1,62,},
{1,166,2,88,1,48,2,83,1,76,2,143,1,63,},
{1,166,2,88,1,48,2,83,1,77,2,142,1,63,},
{1,165,2,90,1,48,2,81,1,78,2,141,1,64,},
{1,62,2,193,1,48,2,39,1,121,2,140,1,64,},
{1,62,2,194,1,47,2,39,1,121,2,139,1,65,},
{1,63,2,193,1,48,2,37,1,123,2,137,1,66,},
{1,64,2,192,1,48,2,36,1,124,2,136,1,67,},
{1,64,2,193,1,48,2,34,1,126,2,135,1,67,},
{1,65,2,192,1,48,2,34,1,126,2,134,1,68,},
{1,65,2,192,1,48,2,33,1,127,2,134,1,68,},
{1,66,2,192,1,48,2,31,1,129,2,132,1,69,},
{1,67,2,191,1,48,2,31,1,129,2,132,1,69,},
{1,67,2,191,1,48,2,30,1,130,2,131,1,70,},
{1,68,2,191,1,48,2,28,1,132,2,129,1,71,},
{1,69,2,190,1,48,2,28,1,132,2,129,1,71,},
{1,69,2,190,1,48,2,27,1,133,2,128,1,72,},
{1,70,2,190,1,48,2,25,1,135,2,127,1,72,},
{1,71,2,189,1,48,2,25,1,135,2,126,1,73,},
{1,71,2,189,1,48,2,24,1,136,2,125,1,74,},
{1,72,2,189,1,48,2,22,1,137,2,124,1,75,},
{1,72,2,189,1,48,2,22,1,137,2,124,1,75,},
{1,73,2,188,1,48,2,21,1,138,2,123,1,76,},
{1,74,2,188,1,47,2,20,1,139,2,122,1,77,},
{1,74,2,188,1,48,2,19,1,139,2,122,1,77,},
{1,75,2,187,1,48,2,18,1,141,2,120,1,78,},
{1,76,2,186,1,48,2,17,1,142,2,120,1,78,},
{1,76,2,187,1,48,2,16,1,142,2,119,1,79,},
{1,77,2,186,1,48,2,15,1,142,2,119,1,80,},
{1,78,2,186,1,47,2,14,1,143,2,119,1,80,},
{1,78,2,186,1,48,2,13,1,143,2,118,1,81,},
{1,79,2,185,1,48,2,12,1,144,2,117,1,82,},
{1,80,2,184,1,48,2,11,1,145,2,116,1,83,},
{1,80,2,185,1,48,2,10,1,145,2,116,1,83,},
{1,81,2,184,1,48,2,9,1,146,2,115,1,84,},
{1,82,2,183,1,49,2,7,1,147,2,115,1,84,},
{1,82,2,184,1,48,2,7,1,146,2,115,1,85,},
{1,83,2,183,1,48,2,6,1,147,2,114,1,86,},
{1,84,2,183,1,47,2,6,1,147,2,113,1,87,},
{1,84,2,183,1,48,2,4,1,148,2,113,1,87,},
{1,85,2,182,1,48,2,3,1,148,2,113,1,88,},
{1,86,2,182,1,47,2,2,1,149,2,112,1,89,},
{1,87,2,181,1,48,2,1,1,149,2,111,1,90,},
{1,87,2,181,1,197,2,112,1,90,},
{1,88,2,181,1,196,2,111,1,91,},
{1,89,2,180,1,195,2,111,1,92,},
{1,90,2,179,1,195,2,111,1,92,},
{1,90,2,180,1,193,2,111,1,93,},
{1,91,2,179,1,193,2,110,1,94,},
{1,92,2,178,1,97,2,17,1,78,2,110,1,95,},
{1,93,2,177,1,96,2,19,1,77,2,110,1,95,},
{1,93,2,178,1,95,2,19,1,76,2,110,1,96,},
{1,94,2,177,1,94,2,21,1,74,2,110,1,97,},
{1,95,2,177,1,92,2,22,1,73,2,111,1,97,},
{1,95,2,177,1,92,2,23,1,72,2,110,1,98,},
{1,96,2,176,1,91,2,25,1,70,2,110,1,99,},
{1,97,2,176,1,89,2,27,1,68,2,110,1,100,},
{1,97,2,176,1,88,2,29,1,66,2,111,1,100,},
{1,98,2,175,1,88,2,30,1,64,2,111,1,101,},
{1,99,2,175,1,86,2,32,1,62,2,111,1,102,},
{1,100,2,174,1,85,2,34,1,60,2,111,1,103,},
{1,101,2,173,1,85,2,35,1,58,2,112,1,103,},
{1,101,2,174,1,83,2,38,1,55,2,112,1,104,},
{1,102,2,173,1,83,2,39,1,52,2,113,1,105,},
{1,103,2,172,1,82,2,41,1,50,2,113,1,106,},
{1,104,2,172,1,80,2,44,1,46,2,114,1,107,},
{1,104,2,172,1,80,2,46,1,43,2,115,1,107,},
{1,105,2,171,1,79,2,48,1,40,2,116,1,108,},
{1,106,2,171,1,77,2,52,1,34,2,118,1,109,},
{1,107,2,170,1,76,2,55,1,30,2,119,1,110,},
{1,108,2,169,1,76,2,59,1,23,2,122,1,110,},
{1,108,2,170,1,74,2,65,1,13,2,126,1,111,},
{1,109,2,169,1,73,2,204,1,112,},
{1,110,2,168,1,73,2,203,1,113,},
{1,111,2,167,1,72,2,203,1,114,},
{1,111,2,168,1,70,2,203,1,115,},
{1,112,2,167,1,70,2,203,1,115,},
{1,113,2,167,1,68,2,203,1,116,},
{1,114,2,166,1,68,2,202,1,117,},
{1,115,2,165,1,67,2,202,1,118,},
{1,116,2,164,1,66,2,202,1,119,},
{1,116,2,165,1,64,2,203,1,119,},
{1,117,2,164,1,64,2,202,1,120,},
{1,118,2,164,1,62,2,202,1,121,},
{1,119,2,163,1,62,2,201,1,122,},
{1,120,2,162,1,61,2,202,1,122,},
{1,120,2,163,1,59,2,202,1,123,},
{1,121,2,162,1,58,2,202,1,124,},
{1,122,2,161,1,58,2,201,1,125,},
{1,123,2,161,1,56,2,201,1,126,},
{1,124,2,160,1,55,2,201,1,127,},
{1,124,2,160,1,55,2,200,1,128,},
{1,125,2,159,1,54,2,201,1,128,},
{1,126,2,159,1,52,2,201,1,129,},
{1,127,2,158,1,52,2,200,1,130,},
{1,128,2,158,1,50,2,200,1,131,},
{1,129,2,157,1,49,2,200,1,132,},
{1,130,2,156,1,49,2,200,1,132,},
{1,131,2,156,1,47,2,200,1,133,},
{1,132,2,155,1,47,2,199,1,134,},
{1,132,2,155,1,46,2,199,1,135,},
{1,133,2,155,1,44,2,199,1,136,},
{1,134,2,154,1,44,2,198,1,137,},
{1,135,2,153,1,43,2,198,1,138,},
{1,136,2,153,1,41,2,198,1,139,},
{1,136,2,153,1,40,2,199,1,139,},
{1,137,2,152,1,40,2,198,1,140,},
{1,138,2,152,1,38,2,198,1,141,},
{1,139,2,151,1,37,2,198,1,142,},
{1,140,2,150,1,37,2,197,1,143,},
{1,141,2,150,1,35,2,197,1,144,},
{1,142,2,149,1,34,2,197,1,145,},
{1,143,2,148,1,34,2,197,1,145,},
{1,144,2,147,1,33,2,197,1,146,},
{1,145,2,147,1,32,2,196,1,147,},
{1,145,2,147,1,31,2,196,1,148,},
{1,146,2,147,1,29,2,196,1,149,},
{1,147,2,146,1,28,2,196,1,150,},
{1,148,2,145,1,28,2,195,1,151,},
{1,149,2,145,1,26,2,195,1,152,},
{1,150,2,144,1,26,2,195,1,152,},
{1,151,2,143,1,25,2,194,1,154,},
{1,152,2,142,1,24,2,195,1,154,},
{1,152,2,143,1,22,2,195,1,155,},
{1,153,2,142,1,22,2,194,1,156,},
{1,154,2,142,1,20,2,194,1,157,},
{1,155,2,141,1,20,2,193,1,158,},
{1,156,2,140,1,19,2,193,1,159,},
{1,157,2,140,1,17,2,193,1,160,},
{1,158,2,139,1,16,2,193,1,161,},
{1,159,2,138,1,16,2,192,1,162,},
{1,160,2,138,1,14,2,193,1,162,},
{1,161,2,137,1,14,2,192,1,163,},
{1,162,2,136,1,13,2,192,1,164,},
{1,162,2,136,1,12,2,192,1,165,},
{1,163,2,136,1,11,2,191,1,166,},
{1,164,2,135,1,10,2,191,1,167,},
{1,165,2,134,1,9,2,191,1,168,},
{1,166,2,134,1,8,2,190,1,169,},
{1,167,2,133,1,7,2,190,1,170,},
{1,168,2,132,1,6,2,190,1,171,},
{1,169,2,132,1,4,2,190,1,172,},
{1,170,2,131,1,4,2,189,1,173,},
{1,171,2,131,1,2,2,189,1,174,},
{1,172,2,130,1,2,2,189,1,174,},
{1,173,2,319,1,175,},
{1,173,2,318,1,176,},
{1,175,2,315,1,177,},
{1,176,2,313,1,178,},
{1,176,2,312,1,179,},
{1,177,2,310,1,180,},
{1,178,2,308,1,181,},
{1,179,2,306,1,182,},
{1,180,2,304,1,183,},
{1,181,2,302,1,184,},
{1,182,2,301,1,184,},
{1,183,2,299,1,185,},
{1,184,2,296,1,187,},
{1,185,2,295,1,187,},
{1,186,2,293,1,188,},
{1,186,2,292,1,189,},
{1,187,2,290,1,190,},
{1,188,2,288,1,191,},
{1,189,2,286,1,192,},
{1,190,2,284,1,193,},
{1,191,2,282,1,194,},
{1,192,2,280,1,195,},
{1,193,2,278,1,196,},
{1,194,2,276,1,197,},
{1,195,2,274,1,198,},
{1,196,2,273,1,198,},
{1,197,2,271,1,199,},
{1,198,2,268,1,201,},
{1,199,2,267,1,201,},
{1,199,2,266,1,202,},
{1,200,2,264,1,203,},
{1,201,2,262,1,204,},
{1,202,2,260,1,205,},
{1,203,2,258,1,206,},
{1,204,2,256,1,207,},
{1,205,2,254,1,208,},
{1,206,2,252,1,209,},
{1,207,2,250,1,210,},
{1,208,2,248,1,211,},
{1,209,2,246,1,212,},
{1,210,2,245,1,212,},
{1,211,2,242,1,214,},
{1,212,2,240,1,215,},
{1,213,2,238,1,216,},
{1,214,2,236,1,217,},
{1,215,2,234,1,218,},
{1,216,2,232,1,219,},
{1,216,2,232,1,219,},
{1,217,2,230,1,220,},
{1,218,2,228,1,221,},
{1,219,2,226,1,222,},
{1,220,2,224,1,223,},
{1,221,2,222,1,224,},
{1,222,2,220,1,225,},
{1,223,2,218,1,226,},
{1,224,2,216,1,227,},
{1,225,2,214,1,228,},
{1,226,2,212,1,229,},
{1,227,2,210,1,230,},
{1,228,2,208,1,231,},
{1,229,2,207,1,231,},
{1,230,2,205,1,232,},
{1,230,2,204,1,233,},
{1,231,2,202,1,234,},
{1,232,2,200,1,235,},
{1,233,2,198,1,236,},
{1,234,2,196,1,237,},
{1,235,2,194,1,238,},
{1,236,2,192,1,239,},
{1,237,2,190,1,240,},
{1,238,2,189,1,240,},
{1,239,2,187,1,241,},
{1,240,2,184,1,243,},
{1,240,2,184,1,243,},
{1,241,2,182,1,244,},
{1,242,2,180,1,245,},
{1,243,2,178,1,246,},
{1,244,2,176,1,247,},
{1,245,2,174,1,248,},
{1,246,2,172,1,249,},
{1,247,2,170,1,250,},
{1,248,2,168,1,251,},
{1,249,2,167,1,251,},
{1,250,2,165,1,252,},
{1,251,2,163,1,253,},
{1,251,2,162,1,254,},
{1,252,2,160,1,255,},
{1,253,2,158,1,256,},
{1,254,2,156,1,257,},
{1,255,2,154,1,258,},
{1,256,2,152,1,259,},
{1,257,2,150,1,260,},
{1,258,2,148,1,261,},
{1,259,2,146,1,262,},
{1,259,2,146,1,262,},
{1,260,2,144,1,263,},
{1,261,2,142,1,264,},
{1,262,2,140,1,265,},
{1,263,2,138,1,266,},
{1,264,2,136,1,267,},
{1,265,2,135,1,267,},
{1,265,2,134,1,268,},
{1,266,2,132,1,269,},
{1,267,2,130,1,270,},
{1,268,2,128,1,271,},
{1,269,2,126,1,272,},
{1,270,2,124,1,273,},
{1,271,2,122,1,274,},
{1,272,2,120,1,275,},
{1,272,2,120,1,275,},
{1,273,2,118,1,276,},
{1,274,2,116,1,277,},
{1,275,2,114,1,278,},
{1,276,2,112,1,279,},
{1,277,2,110,1,280,},
{1,278,2,109,1,280,},
{1,278,2,108,1,281,},
{1,279,2,106,1,282,},
{1,280,2,104,1,283,},
{1,281,2,102,1,284,},
{1,282,2,100,1,285,},
{1,282,2,99,1,286,},
{1,283,2,98,1,286,},
{1,284,2,96,1,287,},
{1,285,2,94,1,288,},
{1,286,2,92,1,289,},
{1,287,2,90,1,290,},
{1,288,2,88,1,291,},
{1,288,2,88,1,291,},
{1,289,2,86,1,292,},
{1,290,2,84,1,293,},
{1,291,2,82,1,294,},
{1,292,2,80,1,295,},
{1,292,2,79,1,296,},
{1,293,2,77,1,297,},
{1,294,2,76,1,297,},
{1,295,2,74,1,298,},
{1,296,2,72,1,299,},
{1,297,2,70,1,300,},
{1,298,2,67,1,302,},
{1,300,2,64,1,303,},
{1,301,2,62,1,304,},
{1,302,2,60,1,305,},
{1,303,2,58,1,306,},
{1,304,2,56,1,307,},
{1,306,2,52,1,309,},
{1,307,2,50,1,310,},
{1,308,2,48,1,311,},
{1,310,2,44,1,313,},
{1,311,2,41,1,315,},
{1,313,2,37,1,317,},
{1,316,2,32,1,319,},
{1,318,2,28,1,321,},
{1,322,2,20,1,325,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
{1,667,},
}
}

View File

@ -0,0 +1 @@
return require 'map_gen.maps.space_race.map_gen.map'

View File

@ -0,0 +1,179 @@
local cliffs = {}
local Public = {}
local orientation = {
['none-to-west'] = 'east-to-none',
['west-to-none'] = 'none-to-east',
['east-to-none'] = 'none-to-west',
['none-to-east'] = 'west-to-none',
['north-to-west'] = 'east-to-north',
['west-to-north'] = 'north-to-east',
['north-to-east'] = 'west-to-north',
['east-to-north'] = 'north-to-west',
['west-to-south'] = 'south-to-east',
['south-to-west'] = 'east-to-south',
['east-to-south'] = 'south-to-west',
['south-to-east'] = 'west-to-south',
['north-to-south'] = 'south-to-north',
['south-to-north'] = 'north-to-south',
['north-to-none'] = 'none-to-north',
['none-to-north'] = 'north-to-none',
['south-to-none'] = 'none-to-south',
['none-to-south'] = 'south-to-none'
}
function Public.cliff(_, _, world)
local world_x = math.abs(world.x) -- 0 = 0
local world_y = world.y + 0.5 -- 0 = 0.5
local _x = cliffs[world_x]
if _x then
local _y = _x[world_y]
if _y then
local cliff_orientation = _y[1]
if world.x < 0 then
local flipped_orientation = orientation[_y[1]]
if flipped_orientation then
cliff_orientation = flipped_orientation
end
end
return {name = 'cliff', cliff_orientation = cliff_orientation, always_place = true, destructible = false}
end
end
end
function Public.generate_cliffs(surface)
for _x, ys in pairs(cliffs) do
for _y, cliff_orientation in pairs(ys) do
local cliff = surface.create_entity{name = 'cliff', position = {x = _x, y = _y}, cliff_orientation = cliff_orientation[1]}
cliff.destructible = false
--inverting
cliff = surface.create_entity{name = 'cliff', position = {x = -_x, y = _y}, cliff_orientation = orientation[cliff_orientation[1]] or cliff_orientation[1]}
cliff.destructible = false
end
end
end
cliffs = {
[378] = {
[-29.5] = {'none-to-west'},
[-17.5] = {'east-to-west'},
[18.5] = {'west-to-east'},
[30.5] = {'west-to-none'}
},
[366] = {
[-25.5] = {'north-to-west'},
[-29.5] = {'east-to-south'},
[-9.5] = {'north-to-west'},
[-13.5] = {'east-to-south'},
[10.5] = {'west-to-south'},
[14.5] = {'north-to-east'},
[26.5] = {'west-to-south'},
[30.5] = {'north-to-east'}
},
[370] = {
[-29.5] = {'east-to-west'},
[-13.5] = {'north-to-west'},
[-17.5] = {'east-to-south'},
[14.5] = {'west-to-south'},
[18.5] = {'north-to-east'},
[30.5] = {'west-to-east'}
},
[374] = {
[-29.5] = {'east-to-west'},
[-17.5] = {'east-to-west'},
[18.5] = {'west-to-east'},
[30.5] = {'west-to-east'}
},
[362] = {
[-21.5] = {'north-to-west'},
[-25.5] = {'east-to-south'},
[-9.5] = {'east-to-none'},
[-5.5] = {'north-to-none'},
[6.5] = {'east-to-none'},
[10.5] = {'none-to-east'},
[22.5] = {'west-to-south'},
[26.5] = {'north-to-east'}
},
[358] = {
[-17.5] = {'north-to-west'},
[-21.5] = {'east-to-south'},
[18.5] = {'west-to-south'},
[22.5] = {'north-to-east'}
},
[354] = {
[-13.5] = {'north-to-west'},
[-17.5] = {'east-to-south'},
[14.5] = {'west-to-south'},
[18.5] = {'north-to-east'}
},
[382] = {
[-17.5] = {'east-to-west'},
[18.5] = {'west-to-east'}
},
[350] = {
[-13.5] = {'east-to-south'},
[-9.5] = {'north-to-south'},
[-5.5] = {'north-to-south'},
[-1.5] = {'north-to-south'},
[2.5] = {'north-to-south'},
[6.5] = {'north-to-south'},
[10.5] = {'north-to-south'},
[14.5] = {'north-to-east'}
}
}
return Public
--[[
31 | 350, 2.5 | north-to-south
  32 | 350, 6.5 | north-to-south
  33 | 362, 6.5 | east-to-none
  34 | 350, 10.5 | north-to-south
  35 | 362, 10.5 | none-to-east
  36 | 366, 10.5 | west-to-south
  37 | 350, 14.5 | north-to-east
  38 | 366, 14.5 | north-to-east
  39 | 354, 14.5 | west-to-south
  40 | 370, 14.5 | west-to-south
  41 | 354, 18.5 | north-to-east
  42 | 370, 18.5 | north-to-east
  43 | 358, 18.5 | west-to-south
  44 | 374, 18.5 | west-to-east
  45 | 378, 18.5 | west-to-east
  52 | 382, 18.5 | west-to-east
  53 | 358, 22.5 | north-to-east
  54 | 362, 22.5 | west-to-south
  55 | 362, 26.5 | north-to-east
  56 | 366, 26.5 | west-to-south
  57 | 366, 30.5 | north-to-east
  58 | 370, 30.5 | west-to-east
  65 | 374, 30.5 | west-to-east
  71 | 378, 30.5 | west-to-none
1 | 378, -29.5 | none-to-west
  2 | 366, -25.5 | north-to-west
  3 | 366, -29.5 | east-to-south
  4 | 370, -29.5 | east-to-west
  5 | 374, -29.5 | east-to-west
  6 | 362, -21.5 | north-to-west
  7 | 362, -25.5 | east-to-south
  8 | 358, -17.5 | north-to-west
  9 | 358, -21.5 | east-to-south
  10 | 354, -13.5 | north-to-west
  11 | 354, -17.5 | east-to-south
  12 | 370, -13.5 | north-to-west
  13 | 370, -17.5 | east-to-south
  14 | 374, -17.5 | east-to-west
  15 | 378, -17.5 | east-to-west
  16 | 382, -17.5 | east-to-west
  23 | 350, -13.5 | east-to-south
  24 | 366, -9.5 | north-to-west
  25 | 366, -13.5 | east-to-south
  26 | 350, -9.5 | north-to-south
  27 | 362, -9.5 | east-to-none
  28 | 350, -5.5 | north-to-south
  29 | 362, -5.5 | north-to-none
  30 | 350, -1.5 | north-to-south
]]

View File

@ -0,0 +1,79 @@
local Config = {
version = 'v0.4.7',
players_needed_to_start_game = 4,
bootstrap_period = 60 * 60 * 30, -- 30 minutes
player_kill_reward = 25,
entity_kill_rewards = {
['default'] = 1,
['wooden-chest'] = 0,
['gun-turret'] = 5,
['laser-turret'] = 10,
['flamethrower-turret'] = 8,
['artillery-turret'] = 50,
['artillery-wagon'] = 30,
['locomotive'] = 10,
['cargo-wagon'] = 5,
['fluid-wagon'] = 5,
['radar'] = 5
},
disabled_research = {
['military'] = {player = 2, entity = 8},
['military-2'] = {player = 6, entity = 24, unlocks = 'military'},
['military-3'] = {player = 12, entity = 48, unlocks = 'military-2'},
['military-4'] = {player = 24, entity = 96, unlocks = 'military-3'},
['stone-walls'] = {player = 2, entity = 8, invert = true},
['heavy-armor'] = {player = 12, entity = 48, invert = true},
['artillery-shell-range-1'] = nil
},
disabled_recipes = {
'tank',
'rocket-silo'
},
entity_drop_amount = {
--NEEDS BALANCING!
['biter-spawner'] = {low = 2, high = 10, chance = 1},
['spitter-spawner'] = {low = 2, high = 10, chance = 1},
['small-worm-turret'] = {low = 2, high = 5, chance = 0.5},
['medium-worm-turret'] = {low = 5, high = 7, chance = 0.5},
['big-worm-turret'] = {low = 5, high = 10, chance = 0.5},
['behemoth-worm-turret'] = {low = 5, high = 15, chance = 0.4},
-- default is 0, no chance of coins dropping from biters/spitters
['small-biter'] = {low = 1, high = 2, chance = 0.05},
['small-spitter'] = {low = 2, high = 3, chance = 0.05},
['medium-spitter'] = {low = 3, high = 6, chance = 0.05},
['big-spitter'] = {low = 5, high = 15, chance = 0.05},
['behemoth-spitter'] = {low = 20, high = 30, chance = 0.05},
['medium-biter'] = {low = 3, high = 5, chance = 0.05},
['big-biter'] = {low = 3, high = 8, chance = 0.05},
['behemoth-biter'] = {low = 8, high = 10, chance = 0.05}
},
turret_active_delays = {
['ammo-turret'] = 60 * 3,
['electric-turret'] = 60 * 10,
['fluid-turret'] = 60 * 5,
['artillery-turret'] = 60 * 60
},
warning_on_built = {
['artillery-turret'] = true,
['artillery-wagon'] = true,
['tank'] = true
},
neutral_entities = {
['wooden-chest'] = true
},
snake = {
size = 45,
max_food = 8,
speed = 30
},
map_gen = { -- Does not yet support being changed!
width_1 = 256,
width_2 = 256,
width_3 = 9
},
game_mode = {
king_of_the_hill = true
}
}
return Config

View File

@ -0,0 +1,120 @@
local Gui = require 'utils.gui'
local Public = {}
-- <Join GUI start>
local join_USA = Gui.uid_name()
local join_USSR = Gui.uid_name()
function Public.show_gui(event)
local frame
local player = game.get_player(event.player_index)
local center = player.gui.center
local gui = center['Space-Race-Lobby']
if (gui) then
Gui.destroy(gui)
end
frame = player.gui.center.add {name = 'Space-Race-Lobby', type = 'frame', direction = 'vertical', style = 'captionless_frame'}
frame.style.minimal_width = 300
--Header
local top_flow = frame.add {type = 'flow', direction = 'horizontal'}
top_flow.style.horizontal_align = 'center'
top_flow.style.horizontally_stretchable = true
local title_flow = top_flow.add {type = 'flow'}
title_flow.style.horizontal_align = 'center'
title_flow.style.top_padding = 8
title_flow.style.horizontally_stretchable = false
local title = title_flow.add {type = 'label', caption = 'Welcome to Space Race'}
title.style.font = 'default-large-bold'
--Body
local content_flow = frame.add {type = 'flow', direction = 'horizontal'}
content_flow.style.top_padding = 8
content_flow.style.bottom_padding = 16
content_flow.style.left_padding = 24
content_flow.style.right_padding = 24
content_flow.style.horizontal_align = 'center'
content_flow.style.horizontally_stretchable = true
local label_flow = content_flow.add {type = 'flow'}
label_flow.style.horizontal_align = 'center'
label_flow.style.horizontally_stretchable = true
local label = label_flow.add {type = 'label', caption = 'Feel free to pick a side!'}
label.style.horizontal_align = 'center'
label.style.single_line = false
label.style.font = 'default'
--Footer
local button_flow = frame.add {type = 'flow'}
button_flow.style.horizontal_align = 'center'
button_flow.style.horizontally_stretchable = true
local usa_button_flow = button_flow.add {type = 'flow', direction = 'vertical'}
usa_button_flow.style.horizontally_stretchable = true
usa_button_flow.style.horizontal_align = 'center'
local ussr_button_flow = button_flow.add {type = 'flow', direction = 'vertical'}
ussr_button_flow.style.horizontally_stretchable = true
ussr_button_flow.style.horizontal_align = 'center'
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
local usa_players = #force_USA.players
local ussr_players = #force_USSR.players
local usa_connected = #force_USA.connected_players
local ussr_connected = #force_USSR.connected_players
label = usa_button_flow.add {type = 'label', caption = usa_connected .. ' online / ' .. usa_players .. ' total'}
label.style.horizontal_align = 'center'
label.style.single_line = false
label.style.font = 'default'
local join_usa_button = usa_button_flow.add {type = 'button', name = join_USA, caption = 'Join United Factory Workers'}
label = ussr_button_flow.add {type = 'label', caption = ussr_connected .. ' online / ' .. ussr_players .. ' total'}
label.style.horizontal_align = 'center'
label.style.single_line = false
label.style.font = 'default'
local join_ussr_button = ussr_button_flow.add {type = 'button', name = join_USSR, caption = 'Join Union of Factory Employees'}
Gui.set_data(join_usa_button, frame)
Gui.set_data(join_ussr_button, frame)
end
Gui.on_click(
join_USA,
function(event)
--local frame = Gui.get_data(event.element)
local player = event.player
--Gui.destroy(frame)
remote.call('space-race', 'join_usa', nil, player)
remote.call('space-race-lobby', 'update_gui')
end
)
Gui.on_click(
join_USSR,
function(event)
--local frame = Gui.get_data(event.element)
local player = event.player
--Gui.destroy(frame)
remote.call('space-race', 'join_ussr', nil, player)
remote.call('space-race-lobby', 'update_gui')
end
)
-- <Join GUI end>
return Public

View File

@ -0,0 +1,102 @@
local Gui = require 'utils.gui'
local Color = require 'resources.color_presets'
local Public = {}
-- <Load GUI start>
function Public.show_gui(event, message)
local frame
local player = game.get_player(event.player_index)
local center = player.gui.center
local gui = center['Space-Race-Wait']
if (gui) then
Gui.destroy(gui)
end
local show_timer = message == nil
local caption = message or 'Waiting for map to generate\n\n... Please wait ...\n'
frame = player.gui.center.add {name = 'Space-Race-Wait', type = 'frame', direction = 'vertical', style = 'captionless_frame'}
frame.style.minimal_width = 300
--Header
local top_flow = frame.add {type = 'flow', direction = 'horizontal'}
top_flow.style.horizontal_align = 'center'
top_flow.style.horizontally_stretchable = true
local title_flow = top_flow.add {type = 'flow'}
title_flow.style.horizontal_align = 'center'
title_flow.style.top_padding = 8
title_flow.style.horizontally_stretchable = false
local title = title_flow.add {type = 'label', caption = 'Welcome to Space Race'}
title.style.font = 'default-large-bold'
--Body
local content_flow = frame.add {type = 'flow'}
content_flow.style.top_padding = 8
content_flow.style.horizontal_align = 'center'
content_flow.style.horizontally_stretchable = true
local label_flow = content_flow.add {type = 'flow', direction = 'vertical'}
label_flow.style.horizontal_align = 'center'
label_flow.style.horizontally_stretchable = true
local label = label_flow.add {type = 'label', caption = caption}
label.style.horizontal_align = 'center'
label.style.single_line = false
label.style.font = 'default'
label.style.font_color = Color.yellow
if show_timer then
local started_tick = remote.call('space-race', 'get_started_tick')
local time = game.tick - started_tick
if time > 60 then
local minutes = (time / 3600)
minutes = minutes - minutes % 1
time = time - (minutes * 3600)
local seconds = (time / 60)
seconds = seconds - seconds % 1
time = minutes .. ' minutes and ' .. seconds .. ' seconds'
else
local seconds = (time - (time % 60)) / 60
time = seconds .. ' seconds'
end
label = label_flow.add {type = 'label', caption = '[color=blue]Time elapsed: ' .. time .. ' [/color]'}
label.style.horizontal_align = 'center'
label.style.single_line = false
label.style.font = 'default'
end
end
-- <Load GUI end>
function Public.show_gui_to_all(message)
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
for _, player in pairs(game.connected_players) do
local force = player.force
if force == force_USSR or force == force_USA then
Public.show_gui({player_index = player.index}, message)
end
end
end
function Public.remove_gui()
for _, player in pairs(game.players) do
local center = player.gui.center
local gui = center['Space-Race-Wait']
if (gui) then
Gui.destroy(gui)
end
end
end
return Public

View File

@ -0,0 +1,91 @@
local Gui = require 'utils.gui'
local snake_game = require 'features.snake.game'
local config = require 'map_gen.maps.space_race.config'
local players_needed = config.players_needed_to_start_game
local Public = {}
-- <Waiting GUI start>
local waiting_close_name = Gui.uid_name()
function Public.show_gui(event)
local frame
local player = game.get_player(event.player_index)
local center = player.gui.center
local gui = center['Space-Race-Lobby']
if (gui) then
Gui.destroy(gui)
end
local snake_button_text
if snake_game.is_running() then
snake_button_text = 'Play Snake'
else
snake_button_text = '... Loading Snake ...'
end
frame = player.gui.center.add {name = 'Space-Race-Lobby', type = 'frame', direction = 'vertical', style = 'captionless_frame'}
frame.style.minimal_width = 300
--Header
local top_flow = frame.add {type = 'flow', direction = 'horizontal'}
top_flow.style.horizontal_align = 'center'
top_flow.style.horizontally_stretchable = true
local title_flow = top_flow.add {type = 'flow'}
title_flow.style.horizontal_align = 'center'
title_flow.style.top_padding = 8
title_flow.style.horizontally_stretchable = false
local title = title_flow.add {type = 'label', caption = 'Welcome to Space Race'}
title.style.font = 'default-large-bold'
--Body
local content_flow = frame.add {type = 'flow', direction = 'horizontal'}
content_flow.style.top_padding = 8
content_flow.style.bottom_padding = 16
content_flow.style.left_padding = 24
content_flow.style.right_padding = 24
content_flow.style.horizontal_align = 'center'
content_flow.style.horizontally_stretchable = true
local label_flow = content_flow.add {type = 'flow'}
label_flow.style.horizontal_align = 'center'
label_flow.style.horizontally_stretchable = true
local label = label_flow.add {type = 'label', caption = #game.connected_players .. ' out of ' .. players_needed .. ' players needed to begin!'}
label.style.horizontal_align = 'center'
label.style.single_line = false
label.style.font = 'default'
--Footer
local ok_button_flow = frame.add {type = 'flow'}
ok_button_flow.style.horizontally_stretchable = true
ok_button_flow.style.horizontal_align = 'center'
local ok_button = ok_button_flow.add {type = 'button', name = waiting_close_name, caption = snake_button_text}
Gui.set_data(ok_button, frame)
end
Gui.on_click(
waiting_close_name,
function(event)
if snake_game.is_running() then
local frame = Gui.get_data(event.element)
local player = event.player
game.permissions.get_group('lobby').remove_player(player)
snake_game.new_snake(player)
Gui.destroy(frame)
end
end
)
-- <Waiting GUI end>
return Public

View File

@ -0,0 +1,88 @@
local Gui = require 'utils.gui'
local snake_game = require 'features.snake.game'
local Public = {}
-- <Won GUI start>
local won_close_name = Gui.uid_name()
function Public.show_gui(event, force)
local frame
local player = game.get_player(event.player_index)
local center = player.gui.center
local gui = center['Space-Race-Lobby']
if (gui) then
Gui.destroy(gui)
end
local snake_button_text
if snake_game.is_running() then
snake_button_text = 'Play Snake'
else
snake_button_text = '... Loading Snake ...'
end
frame = player.gui.center.add {name = 'Space-Race-Lobby', type = 'frame', direction = 'vertical', style = 'captionless_frame'}
frame.style.minimal_width = 300
--Header
local top_flow = frame.add {type = 'flow', direction = 'horizontal'}
top_flow.style.horizontal_align = 'center'
top_flow.style.horizontally_stretchable = true
local title_flow = top_flow.add {type = 'flow'}
title_flow.style.horizontal_align = 'center'
title_flow.style.top_padding = 8
title_flow.style.horizontally_stretchable = false
local title = title_flow.add {type = 'label', caption = 'Welcome to Space Race'}
title.style.font = 'default-large-bold'
--Body
local content_flow = frame.add {type = 'flow', direction = 'horizontal'}
content_flow.style.top_padding = 8
content_flow.style.bottom_padding = 16
content_flow.style.left_padding = 24
content_flow.style.right_padding = 24
content_flow.style.horizontal_align = 'center'
content_flow.style.horizontally_stretchable = true
local label_flow = content_flow.add {type = 'flow'}
label_flow.style.horizontal_align = 'center'
label_flow.style.horizontally_stretchable = true
local label = label_flow.add {type = 'label', caption = force.name .. ' have won the game!\nWaiting for map restart\n\nPlay some snake while we wait!'}
label.style.horizontal_align = 'center'
label.style.single_line = false
label.style.font = 'default'
--Footer
local ok_button_flow = frame.add {type = 'flow'}
ok_button_flow.style.horizontally_stretchable = true
ok_button_flow.style.horizontal_align = 'center'
local ok_button = ok_button_flow.add {type = 'button', name = won_close_name, caption = snake_button_text}
Gui.set_data(ok_button, frame)
end
Gui.on_click(
won_close_name,
function(event)
if snake_game.is_running() then
local frame = Gui.get_data(event.element)
local player = event.player
game.permissions.get_group('lobby').remove_player(player)
snake_game.new_snake(player)
Gui.destroy(frame)
end
end
)
-- <Won GUI end>
return Public

View File

@ -0,0 +1,197 @@
local Event = require 'utils.event'
local Token = require 'utils.token'
local Task = require 'utils.task'
local b = require 'map_gen.shared.builders'
local snake_game = require 'features.snake.game'
local config = require 'map_gen.maps.space_race.config'
local Gui = require 'utils.gui'
--Guis
local join_gui = require 'map_gen.maps.space_race.gui.join_gui'
local wait_gui = require 'map_gen.maps.space_race.gui.wait_gui'
local won_gui = require 'map_gen.maps.space_race.gui.won_gui'
local floor = math.floor
local Public = {}
local size = config.snake.size
local snake_check_x = (size + 5) * 2
local snake_check_y = size + 5
--Lobby Map
local Generate = require 'map_gen.shared.generate'
local shape = b.rectangle(size, 4)
shape = b.change_tile(shape, true, 'concrete')
Generate.get_surfaces()['snake'] = shape
local delay_snake_checker
local players_needed = config.players_needed_to_start_game
local function check_snake_map_gen()
local surface = game.get_surface('snake')
return surface.get_tile({snake_check_x, -snake_check_y}).name == 'out-of-map' and surface.get_tile({snake_check_x, snake_check_y}).name == 'out-of-map'
end
local snake_generate =
Token.register(
function()
local surface = game.get_surface('snake')
if check_snake_map_gen() then
local position = {x = -floor(size), y = 5}
local max_food = config.snake.max_food
local speed = config.snake.speed
if not snake_game.is_running() then
snake_game.start_game(surface, position, size, speed, max_food)
end
else
Task.set_timeout_in_ticks(5, delay_snake_checker)
end
end
)
local check_map_gen_is_done
check_map_gen_is_done =
Token.register(
function()
if not snake_game.is_running() then
if check_snake_map_gen() then
Event.remove_removable_nth_tick(60, check_map_gen_is_done)
Token.get(snake_generate)()
Public.update_gui()
return
end
else
Event.remove_removable_nth_tick(60, check_map_gen_is_done)
Public.update_gui()
end
end
)
delay_snake_checker =
Token.register(
function()
Event.add_removable_nth_tick(60, check_map_gen_is_done)
end
)
Event.on_init(
function()
local snake_surface = game.create_surface('snake', {height = 1, width = 1})
game.forces.player.set_spawn_position({x = 0, y = 0}, snake_surface)
local y = 128
local x = 128
game.forces.player.chart(snake_surface, {lefttop = {x = -x, y = -y}, rightbottom = {x = x, y = y}})
Task.set_timeout_in_ticks(60 * 3, delay_snake_checker)
end
)
function Public.show_gui(event)
if #game.connected_players < players_needed and (not remote.call('space-race', 'get_game_status')) then
if not snake_game.is_running() and game.tick > 60 * 55 then
Token.get(snake_generate)()
end
game.forces.enemy.evolution_factor = 0
wait_gui.show_gui(event)
return
end
local won = remote.call('space-race', 'get_won')
if won then
won_gui.show_gui(event, won)
else
if snake_game.is_running() then
snake_game.end_game()
end
join_gui.show_gui(event)
end
end
function Public.update_gui()
local players = game.connected_players
for i = 1, #players do
local player = players[i]
local center = player.gui.center
local gui = center['Space-Race-Lobby']
if (gui) then
if player.force.name == 'player' then
Public.show_gui({player_index = player.index})
else
Gui.destroy(gui)
end
end
end
end
local function on_snake_player_died(event)
local player = event.player
game.permissions.get_group('lobby').add_player(player)
Public.show_gui({player_index = player.index})
player.teleport({0, 0}, game.get_surface('snake'))
end
local function to_lobby(player_index)
local player = game.get_player(player_index)
player.teleport({0, 0}, game.get_surface('snake'))
game.permissions.get_group('lobby').add_player(player)
local character = player.character
if character and character.valid then
player.character.destroy()
end
player.set_controller {type = defines.controllers.ghost}
Public.show_gui({player_index = player.index})
end
local function on_player_created(event)
to_lobby(event.player_index)
end
local function on_player_joined(event)
local won = remote.call('space-race', 'get_won')
if won then
to_lobby(event.player_index)
end
Public.update_gui()
end
local delay_to_lobby =
Token.register(
function()
local teams = remote.call('space-race', 'get_teams')
game.remove_offline_players()
for i = 1, #teams do
for _, player in pairs(teams[i].connected_players) do
player.force = game.forces.player
to_lobby(player.index)
end
end
end
)
local function on_player_left()
if #game.connected_players < players_needed and (not remote.call('space-race', 'get_game_status')) then
Task.set_timeout_in_ticks(1, delay_to_lobby) -- Other on_player_left_game events would error if we removed offline players instantly
end
Public.update_gui()
end
Event.add(snake_game.events.on_snake_player_died, on_snake_player_died)
Event.add(defines.events.on_player_created, on_player_created)
Event.add(defines.events.on_player_joined_game, on_player_joined)
Event.add(defines.events.on_player_left_game, on_player_left)
function Public.all_to_lobby()
local players = game.connected_players
for i = 1, #players do
to_lobby(players[i].index)
end
Task.set_timeout_in_ticks(5, snake_generate)
end
function Public.to_lobby(player_index)
to_lobby(player_index)
end
remote.add_interface('space-race-lobby', Public)
return Public

View File

@ -0,0 +1,141 @@
require 'map_gen.maps.space_race.scenario'
local b = require 'map_gen.shared.builders'
local RS = require 'map_gen.shared.redmew_surface'
local Map_gen_presets = require 'resources.map_gen_settings'
local Event = require 'utils.event'
local floor = math.floor
local perlin = require 'map_gen.shared.perlin_noise'
local math = require 'utils.math'
local Map_gen_config = (require 'map_gen.maps.space_race.config').map_gen
Event.on_init(
function()
--game.map_settings.enemy_evolution.time_factor = 0.000002
--game.map_settings.enemy_evolution.destroy_factor = 0.000010
--game.map_settings.enemy_evolution.pollution_factor = 0.000075
end
)
local uranium_none = {
autoplace_controls = {
['uranium-ore'] = {
frequency = 1,
richness = 1,
size = 0
}
}
}
RS.set_map_gen_settings({Map_gen_presets.oil_none, uranium_none, Map_gen_presets.ore_none, Map_gen_presets.water_none})
local sand_width = 128
local sand_width_inv = math.tau / sand_width
--perlin options
local noise_variance = 0.025 --The lower this number the smoother the curve is gonna be
local noise_level = 10 --Factor for the magnitude of the curve
local sand_noise_level = noise_level * 0.9
-- Leave nil and they will be set based on the map seed.
local perlin_seed_1 = 17000
local width_1 = Map_gen_config.width_1
local width_2 = Map_gen_config.width_2
local width_3 = Map_gen_config.width_3
local function sand_shape(x, y)
local p = perlin.noise(x * noise_variance, y * noise_variance, perlin_seed_1) * sand_noise_level
p = p + math.sin(x * sand_width_inv) * 2
return p > y
end
local sand_shape_right = b.rotate(sand_shape, -math.pi / 2)
local beach = b.line_y(16)
local beach_right = b.subtract(beach, sand_shape_right)
local beach_left = b.flip_xy(beach_right)
beach_left = b.translate(beach_left, -8, 0)
beach_right = b.translate(beach_right, 8, 0)
local water_transition_right = b.add(beach_right, beach_left)
local water_transition_left = b.flip_xy(water_transition_right)
water_transition_right = b.translate(water_transition_right, floor(width_1 / 2), 0)
water_transition_left = b.translate(water_transition_left, -floor(width_1 / 2), 0)
local water_transition = b.add(water_transition_right, water_transition_left)
local wilderness_shallow_water = b.line_y(width_1)
wilderness_shallow_water = b.change_tile(wilderness_shallow_water, true, 'water-shallow') -- water-mud is also walkable but doesn't have any tile transitions
wilderness_shallow_water = b.if_else(water_transition, wilderness_shallow_water)
local uranium_island = require 'map_gen.maps.space_race.map_gen.uranium_island'
wilderness_shallow_water = b.if_else(uranium_island, wilderness_shallow_water)
local wilderness_land = b.line_y(width_2)
local safe_zone = b.circle(256)
safe_zone = b.subtract(safe_zone, b.translate(b.rectangle(512, 512), -256, 0))
safe_zone = b.translate(safe_zone, -(width_2 / 2 + width_3 / 2), 0)
safe_zone = b.remove_map_gen_enemies(safe_zone)
wilderness_land = b.add(safe_zone, wilderness_land)
local landfill_water = b.circle(128)
local no_cliff_rectangle = b.rectangle(75, 75)
no_cliff_rectangle = b.translate(no_cliff_rectangle, 0, 0)
no_cliff_rectangle = b.remove_map_gen_entities_by_filter(no_cliff_rectangle, {name = 'cliff'})
landfill_water = b.add(no_cliff_rectangle, landfill_water)
landfill_water = b.translate(landfill_water, -(width_2 / 2 + width_3 / 2), 0)
landfill_water = b.remove_map_gen_enemies(landfill_water)
landfill_water = b.change_map_gen_collision_tile(landfill_water, 'water-tile', 'landfill')
landfill_water = b.subtract(landfill_water, b.translate(b.rectangle(256, 256), -256, 0))
-- landfill_water = b.change_tile(landfill_water, true, 'lab-white')
local wilderness_resources = require 'map_gen.maps.space_race.map_gen.wilderness_ores'
local mirrored_water = wilderness_resources[2]
local mirrored_ore = wilderness_resources[1]
mirrored_water = b.subtract(mirrored_water, b.invert(wilderness_land))
wilderness_land = b.add(mirrored_water, wilderness_land)
wilderness_land = b.apply_entity(wilderness_land, mirrored_ore)
-- wilderness_land = b.change_tile(wilderness_land, true, 'lab-white')
wilderness_land = b.add(landfill_water, wilderness_land)
local wilderness_land_left = b.translate(wilderness_land, -(width_1 + width_2) / 2, 0)
local wilderness_land_right = b.translate(b.flip_x(wilderness_land), (width_1 + width_2) / 2, 0)
local wilderness_ditch = b.line_y(width_3)
wilderness_ditch = b.if_else(b.change_tile(b.translate(b.line_y(width_3 - 1), -1, 0), true, 'out-of-map'), wilderness_ditch)
wilderness_ditch = b.if_else(b.change_tile(b.translate(b.rectangle(2, 17), -1, 0), true, 'landfill'), wilderness_ditch)
local rocket_silo_shape = b.rectangle(9, 9)
rocket_silo_shape = b.change_tile(rocket_silo_shape, true, 'landfill')
rocket_silo_shape = b.remove_map_gen_trees(rocket_silo_shape)
wilderness_ditch = b.if_else(rocket_silo_shape, wilderness_ditch)
local wilderness_ditch_left = b.translate(wilderness_ditch, -(width_1 / 2 + width_2 + width_3 / 2), 0)
local wilderness_ditch_right = b.translate(b.rotate(wilderness_ditch, math.pi), (width_1 / 2 + width_2 + width_3 / 2), 0)
local wilderness = b.any({wilderness_shallow_water, wilderness_ditch_left, wilderness_ditch_right, wilderness_land_left, wilderness_land_right})
local limited_safe_zone = require 'map_gen.maps.space_race.map_gen.safe_zone'
local map = b.add(wilderness, limited_safe_zone)
--map = b.if_else(wilderness, b.full_shape)
return map

View File

@ -0,0 +1,67 @@
local b = require 'map_gen.shared.builders'
local Map_gen_config = (require 'map_gen.maps.space_race.config').map_gen
local width_1 = Map_gen_config.width_1
local width_2 = Map_gen_config.width_2
local safe_zone_width = 512
-- Limited Safe zone
local limited_safe_zone = b.rectangle(safe_zone_width, 512)
local landfill_water = b.circle(128)
landfill_water = b.translate(landfill_water, safe_zone_width/2, 0)
landfill_water = b.remove_map_gen_enemies(landfill_water)
landfill_water = b.change_map_gen_collision_tile(landfill_water, 'water-tile', 'landfill')
-- landfill_water = b.change_tile(landfill_water, true, 'lab-white')
local safe_zone_resources = require 'map_gen.maps.space_race.map_gen.safe_zone_ores'
limited_safe_zone = b.apply_entity(limited_safe_zone, safe_zone_resources)
limited_safe_zone = b.add(landfill_water, limited_safe_zone)
limited_safe_zone = b.remove_map_gen_enemies(limited_safe_zone)
limited_safe_zone = b.remove_map_gen_entities_by_filter(limited_safe_zone, {name = 'cliff'})
local small_circle = b.rectangle(40, 40)
local function constant(x)
return function()
return x
end
end
local start_iron = b.resource(small_circle, 'iron-ore', constant(750))
local start_copper = b.resource(small_circle, 'copper-ore', constant(600))
local start_stone = b.resource(small_circle, 'stone', constant(600))
local start_coal = b.resource(small_circle, 'coal', constant(600))
local start_segmented = b.segment_pattern({start_iron, start_iron, start_copper, start_copper, start_iron, start_iron, start_stone, start_coal})
local start_resources = b.apply_entity(small_circle, start_segmented)
local water = b.rectangle(10, 10)
water = b.change_tile(water, true, 'water')
water = b.translate(water, -35, 0)
start_resources = b.add(start_resources, water)
start_resources = b.translate(start_resources, (safe_zone_width/2 - 60), 0)
start_resources = b.change_map_gen_collision_tile(start_resources, 'water-tile', 'landfill')
start_resources = b.remove_map_gen_enemies(start_resources)
limited_safe_zone = b.add(start_resources, limited_safe_zone)
local limited_safe_zone_right = b.translate(limited_safe_zone, -(256 + width_1 / 2 + width_2), 0)
local limited_safe_zone_left = b.translate(b.flip_x(limited_safe_zone), 256 + width_1 / 2 + width_2, 0)
limited_safe_zone = b.add(limited_safe_zone_right, limited_safe_zone_left)
return limited_safe_zone

View File

@ -0,0 +1,92 @@
local b = require 'map_gen.shared.builders'
local Random = require 'map_gen.shared.random'
local table = require 'utils.table'
local Global = require 'utils.global'
local RS = require 'map_gen.shared.redmew_surface'
local Map_gen_config = (require 'map_gen.maps.space_race.config').map_gen
local seed = nil -- set to number to force seed
local seed_2 = nil -- set to number to force seed
local width_2 = Map_gen_config.width_2
local pic = require 'map_gen.data.presets.life'
pic = b.decompress(pic)
local life_shape = b.picture(pic)
life_shape = b.scale(life_shape, 0.05, 0.05)
local function value(base, mult, pow)
return function(x, y)
local d = math.sqrt(x * x + y * y)
return base + mult * d ^ pow
end
end
local function non_transform(shape)
return shape
end
local ores = {
{weight = 275},
{transform = non_transform, resource = 'iron-ore', value = value(500, 0.75, 1.2), weight = 12},
{transform = non_transform, resource = 'copper-ore', value = value(400, 0.75, 1.2), weight = 10},
{transform = non_transform, resource = 'stone', value = value(250, 0.3, 1.05), weight = 3},
{transform = non_transform, resource = 'coal', value = value(400, 0.8, 1.075), weight = 8}
}
local total_ore_weights = {}
local ore_t = 0
for _, v in ipairs(ores) do
ore_t = ore_t + v.weight
table.insert(total_ore_weights, ore_t)
end
local random_ore = Random.new(seed, seed_2)
local ore_pattern = {}
local p_cols = width_2
local p_rows = 32
for r = 1, p_rows do
local row = {}
ore_pattern[r] = row
for c = 1, p_cols do
local i = random_ore:next_int(1, ore_t)
local index = table.binary_search(total_ore_weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local ore_data = ores[index]
local transform = ore_data.transform
if not transform then
row[c] = b.no_entity
else
local ore_shape = transform(life_shape)
local x = random_ore:next_int(-16, 16)
local y = random_ore:next_int(-16, 16)
ore_shape = b.translate(ore_shape, x, y)
ore_shape = b.resource(ore_shape, ore_data.resource, ore_data.value, true)
row[c] = ore_shape
end
end
end
local mirrored_ore = b.grid_pattern_full_overlap(ore_pattern, p_cols, p_rows, 48, 48)
Global.register_init(
{},
function(tbl)
tbl.seed = seed or RS.get_surface().map_gen_settings.seed
tbl.seed_2 = seed_2 or tbl.seed * 2
end,
function(tbl)
seed = tbl.seed
seed_2 = tbl.seed_2
end
)
return mirrored_ore

View File

@ -0,0 +1,164 @@
local b = require 'map_gen.shared.builders'
local Event = require 'utils.event'
local Global = require 'utils.global'
local RS = require 'map_gen.shared.redmew_surface'
local Game_mode_config = (require 'map_gen.maps.space_race.config').game_mode
local island_1_offset = 0
local island_2_offset = -128
local island_3_offset = 128
local crafters = {}
Global.register(
{
crafters = crafters
},
function(tbl)
crafters = tbl.crafters
end
)
local inf = function()
return 100000000
end
local uranium_island = b.circle(10)
uranium_island = b.remove_map_gen_resources(uranium_island)
uranium_island = b.remove_map_gen_trees(uranium_island)
uranium_island = b.remove_map_gen_entities_by_filter(uranium_island, {name = {'cliff', 'simple-entity'}})
if not Game_mode_config.king_of_the_hill then
local uranium_ore = b.resource(b.rectangle(2, 2), 'uranium-ore', inf, true)
uranium_island = b.apply_entity(uranium_island, uranium_ore)
end
local uranium_island_water = b.change_tile(b.circle(20), true, 'water')
local uranium_island_bridge = b.all({b.any({b.line_x(2), b.line_y(2)}), b.circle(20)})
uranium_island_bridge = b.change_tile(uranium_island_bridge, true, 'water-shallow')
uranium_island_water = b.if_else(uranium_island_bridge, uranium_island_water)
uranium_island = b.if_else(uranium_island, uranium_island_water)
local multiple_uranium_island
if Game_mode_config.king_of_the_hill then
multiple_uranium_island = b.add(b.translate(uranium_island, 0, island_2_offset), b.translate(uranium_island, 0, island_1_offset))
multiple_uranium_island = b.add(b.translate(uranium_island, 0, island_3_offset), multiple_uranium_island)
else
multiple_uranium_island = uranium_island
end
if Game_mode_config.king_of_the_hill then
local outpost_1 = {
{name = 'crash-site-lab-broken', position = {0.5, -7.5}},
{name = 'crash-site-generator', position = {0.5, -3}},
{name = 'crash-site-assembling-machine-1-broken', position = {-6.5, 0}},
{name = 'assembling-machine-2', position = {0, 0.5}, recipe = 'low-density-structure'},
{name = 'crash-site-electric-pole', position = {0.25, -1.48828125}},
{name = 'crash-site-assembling-machine-1-broken', position = {6.5, 0}},
{name = 'crash-site-assembling-machine-2-broken', position = {0, 6.5}}
}
local outpost_2 = {
{name = 'crash-site-lab-broken', position = {0.5, -7.5}},
{name = 'crash-site-generator', position = {0.5, -3}},
{name = 'crash-site-assembling-machine-1-broken', position = {-6.5, 0}},
{name = 'crash-site-assembling-machine-2-repaired', position = {0, 0.5}, recipe = 'rocket-control-unit'},
{name = 'crash-site-electric-pole', position = {0.25, -1.48828125}},
{name = 'crash-site-assembling-machine-1-broken', position = {6.5, 0}},
{name = 'crash-site-assembling-machine-2-broken', position = {0, 6.5}}
}
local outpost_3 = {
{name = 'crash-site-generator', position = {x = 0.5, y = -7}, direction = 0},
{name = 'assembling-machine-3', position = {x = -0.5, y = -3.5}, direction = 4, recipe = 'rocket-fuel'},
{name = 'crash-site-electric-pole', position = {x = 0.37109375, y = -5.46875}, direction = 0},
{name = 'storage-tank-remnants', position = {x = -3.5, y = -0.5}, direction = 0},
{name = 'pipe-to-ground', position = {x = -0.5, y = -1.5}, direction = 0},
{name = 'crash-site-electric-pole', position = {x = -0.61328125, y = -0.35546875}, direction = 0},
{name = 'storage-tank-remnants', position = {x = 2.5, y = -0.5}, direction = 0},
{name = 'oil-refinery', position = {x = -0.5, y = 3.5}, direction = 0},
{name = 'pipe-to-ground', position = {x = -0.5, y = 0.5}, direction = 4},
{name = 'offshore-pump', position = {x = -8.5, y = 6.5}, direction = 6},
{name = 'crash-site-electric-pole', position = {x = 2.35546875, y = 4.5546875}, direction = 0},
--{name = 'crude-oil', position = {x = 6.5, y = 5.5}, direction = 0, amount = 1000}, -- Not working somehow
{name = 'pumpjack', position = {x = 6.5, y = 5.5}, direction = 6},
{name = 'pipe', position = {x = -6.5, y = 6.5}, direction = 0},
{name = 'pipe', position = {x = -7.5, y = 6.5}, direction = 0},
{name = 'pipe-to-ground', position = {x = -5.5, y = 6.5}, direction = 6},
{name = 'pipe-to-ground', position = {x = -2.5, y = 6.5}, direction = 2},
{name = 'pipe', position = {x = -1.5, y = 6.5}, direction = 0},
{name = 'pipe', position = {x = 0.5, y = 6.5}, direction = 0},
{name = 'pipe-to-ground', position = {x = 1.5, y = 6.5}, direction = 6},
{name = 'pipe-to-ground', position = {x = 4.5, y = 6.5}, direction = 2},
{name = 'crash-site-electric-pole', position = {x = 6.51171875, y = 7.5546875}, direction = 0}
}
local function register_crafter(entity)
table.insert(crafters, entity)
end
local function lock_entity(e)
e.destructible = false
e.minable = false
e.operable = false
e.rotatable = false
end
Event.on_init(
function()
local surface = RS.get_surface()
for k, entity in pairs(outpost_1) do
entity.position[2] = entity.position[2] + island_1_offset
entity.force = 'neutral'
local e = surface.create_entity(entity)
lock_entity(e)
if entity.recipe then
e.set_recipe('low-density-structure')
e.recipe_locked = true
register_crafter(e)
end
end
for k, entity in pairs(outpost_2) do
entity.position[2] = entity.position[2] + island_2_offset
entity.force = 'neutral'
local e = surface.create_entity(entity)
lock_entity(e)
if entity.recipe then
e.set_recipe('rocket-control-unit')
e.recipe_locked = true
register_crafter(e)
end
end
for k, entity in pairs(outpost_3) do
entity.position.y = entity.position.y + island_3_offset
entity.force = 'neutral'
local e = surface.create_entity(entity)
if not entity.amount then
lock_entity(e)
end
if entity.recipe then
e.set_recipe('rocket-fuel')
e.recipe_locked = true
e.direction = defines.direction.south
register_crafter(e)
end
if entity.name == 'oil-refinery' then
e.set_recipe('advanced-oil-processing')
e.recipe_locked = true
end
end
end
)
Event.on_nth_tick(
600,
function()
if remote.call('space-race', 'get_game_status') then
for _, crafter in pairs(crafters) do
local item = crafter.get_recipe().products[1].name
crafter.get_output_inventory().insert({name = item, count = 1})
end
end
end
)
end
return multiple_uranium_island

View File

@ -0,0 +1,126 @@
local b = require 'map_gen.shared.builders'
local Random = require 'map_gen.shared.random'
local table = require 'utils.table'
local Global = require 'utils.global'
local RS = require 'map_gen.shared.redmew_surface'
local Map_gen_config = (require 'map_gen.maps.space_race.config').map_gen
local seed = nil -- set to number to force seed
local seed_2 = nil -- set to number to force seed
local width_2 = Map_gen_config.width_2
local pic = require 'map_gen.data.presets.death'
pic = b.decompress(pic)
local death_shape = b.picture(pic)
death_shape = b.scale(death_shape, 0.075, 0.075)
local function value(base, mult, pow)
return function(x, y)
local d = math.sqrt(x * x + y * y)
return base + mult * d ^ pow
end
end
local function non_transform(shape)
return shape
end
local function uranium_transform(shape)
return b.scale(shape, 0.75)
end
local function oil_transform(shape)
shape = b.throttle_xy(shape, 1, 5, 1, 5)
return shape
end
local function water_transform(shape)
shape = b.change_tile(shape, true, 'water')
return shape
end
local ores = {
{weight = 200},
{transform = non_transform, resource = 'iron-ore', value = value(500, 0.75, 1.2), weight = 12},
{transform = non_transform, resource = 'copper-ore', value = value(400, 0.75, 1.2), weight = 10},
{transform = non_transform, resource = 'stone', value = value(250, 0.3, 1.05), weight = 3},
{transform = non_transform, resource = 'coal', value = value(400, 0.8, 1.075), weight = 8},
{transform = uranium_transform, resource = 'uranium-ore', value = value(100, 0.3, 1.015), weight = 3},
{transform = oil_transform, resource = 'crude-oil', value = value(180000, 50, 1.1), weight = 6},
{transform = water_transform, weight = 20}
}
local total_ore_weights = {}
local ore_t = 0
for _, v in ipairs(ores) do
ore_t = ore_t + v.weight
table.insert(total_ore_weights, ore_t)
end
local random_ore = Random.new(seed, seed_2)
local ore_pattern = {}
local water_pattern = {}
local p_cols = width_2
local p_rows = 32
for r = 1, p_rows do
local row = {}
ore_pattern[r] = row
local water_row = {}
water_pattern[r] = water_row
for c = 1, p_cols do
local i = random_ore:next_int(1, ore_t)
local index = table.binary_search(total_ore_weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local ore_data = ores[index]
local transform = ore_data.transform
if not transform then
row[c] = b.no_entity
else
local resource = ore_data.resource
local ore_shape
if resource == 'crude-oil' then
ore_shape = transform(b.rectangle(24, 24))
else
ore_shape = transform(death_shape)
end
local x = random_ore:next_int(-16, 16)
local y = random_ore:next_int(-16, 16)
ore_shape = b.translate(ore_shape, x, y)
if not resource then
water_row[c] = ore_shape
row[c] = b.no_entity
else
ore_shape = b.resource(ore_shape, resource, ore_data.value, true)
row[c] = ore_shape
end
end
end
end
local mirrored_ore = b.grid_pattern_full_overlap(ore_pattern, p_cols, p_rows, 48, 48)
local mirrored_water = b.grid_pattern_full_overlap(water_pattern, p_cols, p_rows, 48, 48)
Global.register_init(
{},
function(tbl)
tbl.seed = seed or RS.get_surface().map_gen_settings.seed
tbl.seed_2 = seed_2 or tbl.seed * 2
end,
function(tbl)
seed = tbl.seed
seed_2 = tbl.seed_2
end
)
return {mirrored_ore, mirrored_water}

View File

@ -0,0 +1,80 @@
local ScenarioInfo = require 'features.gui.info'
local config = require 'map_gen.maps.space_race.config'
local entity_kill_rewards = config.entity_kill_rewards
local entity_drop_amount = config.entity_drop_amount
ScenarioInfo.set_map_name('RedMew - Space Race')
--ScenarioInfo.set_map_description('World at War! This is not a cold war, it is a radioative hot war')
ScenarioInfo.set_map_description('Reach space through strategy focused PVP.\nDirect and indirect PVP with safe zones and PVP areas. ')
ScenarioInfo.add_map_extra_info(
[[
- Kill the enemy silo or launch a rocket to win
- Build production infrastucture in your teams' safe zone
- The enemy team can't reach you in your safe zone
- Resources are plentiful in the wilderness
- Explore, exploit and defend the wilderness for extra resources and coins
- Engage in PVP and PVE to earn coins to enable research
- Enemy structures: (balance coming soon)
Turrets ]] .. entity_kill_rewards['gun-turret'] .. '-' .. entity_kill_rewards['artillery-turret'] .. ' coins\n' ..
[[
Radars ]] .. entity_kill_rewards['radar'] .. ' coins\n' ..
[[
Others ]] .. entity_kill_rewards['default'] .. ' coin\n' ..
[[
- Enemy players: ]] .. config.player_kill_reward .. ' coins\n' ..
[[
- Natives:
Units ]] .. entity_drop_amount['small-biter'].low .. '-' .. entity_drop_amount['behemoth-spitter'].high .. ' coins ' .. entity_drop_amount['small-biter'].chance * 100 .. '% chance\n' ..
[[
Worms ]] .. entity_drop_amount['small-worm-turret'].low .. '-' .. entity_drop_amount['behemoth-worm-turret'].high .. ' coins ' .. entity_drop_amount['small-worm-turret'].chance * 100 .. '% chance\n' ..
[[
Spawners ]] .. entity_drop_amount['spitter-spawner'].low .. '-' .. entity_drop_amount['biter-spawner'].high .. ' coins ' .. entity_drop_amount['biter-spawner'].chance * 100 .. '% chance\n' ..
[[
- Sabotage enemy wilderness structures to slow the enemy team
Coming Soon:
- Balance changes
- New research mechanics
- Defend strategic points for free rocket parts
- Vote on game victory conditions:
- King of the Hill
- Capture the Flag
- Team Death Match (Lol. NO)
Current Version: ]] .. config.version
)
ScenarioInfo.set_new_info(
[[
2019-11-16 v0.4.7
- Reduced player movement during combat
2019-10-27 v0.4.6
- Fixes to coin drops
- Fixes for market unlocks
- Total darkness at night
2019-10-27 v0.4.5
- Use /join-UF* to switch team when unbalanced
- 10 seconds buffer before game start after map generation has finished
- Bug fixes
2019-10-27 v0.4
- Custom ore generation
- King of the hill game mode added
- Random research purchasable in the market
- More refactoring
2019-10-12 v0.3
- Cliffs around rocket silo
- Market prices changed
- Wooden chests are now minable for both forces
- Refactoring of code
- Added central config file
2019-10-11 v0.2
- Added water near spawn
- Changed biter coin drop rate
- Market tank purchase warns enemy team
- Balance changes
2019-10-1 v0.01
- Initial alpha tests
]]
)

View File

@ -0,0 +1,533 @@
local Retailer = require 'features.retailer'
local Events = require 'utils.event'
local Token = require 'utils.token'
local Task = require 'utils.task'
local Global = require 'utils.global'
local ScoreTracker = require 'utils.score_tracker'
local MarketItems = require 'map_gen.maps.space_race.market_items'
local unlock_progress = {
force_USA = {
players_killed = 0,
entities_killed = 0
},
force_USSR = {
players_killed = 0,
entities_killed = 0
}
}
local saved_prices = {}
Global.register(
{
unlock_progress = unlock_progress,
saved_prices = saved_prices
},
function(tbl)
unlock_progress = tbl.unlock_progress
saved_prices = tbl.saved_prices
end
)
local config = require 'map_gen.maps.space_race.config'
local entity_kill_rewards = config.entity_kill_rewards
local entity_kill_rewards_default = entity_kill_rewards['default']
local entity_drop_amount = config.entity_drop_amount
local player_kill_reward = config.player_kill_reward
local check_random_research_unlock
local research_tiers = {
['automation-science-pack'] = 1,
['logistic-science-pack'] = 2,
['military-science-pack'] = 3,
['chemical-science-pack'] = 4,
['production-science-pack'] = 5,
['utility-science-pack'] = 6,
['space-science-pack'] = 7 -- Only researches mining productivity
}
local function check_research_tier(tech, tier)
local ingredients = tech.research_unit_ingredients
if tier <= 2 then
return #ingredients == tier
end
for i = 1, #ingredients do
if research_tiers[ingredients[i].name] > tier then
return false
end
end
return true
end
local function random_tech(tier, force, group_name)
local techs = force.technologies
local tech_unlocked = false
local techs_left = false
local tier_name = 'random-tier-' .. tier
for _, technology in pairs(techs) do
local in_tier = check_research_tier(technology, tier)
if (in_tier and technology.researched == false and technology.enabled == true) then
if not tech_unlocked then
tech_unlocked = true
technology.researched = true
force.print('[technology=' .. technology.name .. '] has been purchased and unlocked!')
local items = Retailer.get_items(group_name)
items[tier_name].price = math.ceil(items[tier_name].price * 1.05)
elseif tech_unlocked then
techs_left = true
break
end
end
end
if not techs_left then
local items = Retailer.get_items(group_name)
local price = items[tier_name].price
if not saved_prices[force.name] then
saved_prices[force.name] = {}
end
saved_prices[force.name][tier_name] = price
Retailer.remove_item(group_name, tier_name)
end
end
local function check_heighest_tier(tech)
local ingredients = tech.research_unit_ingredients
local tier = 1
for i = 1, #ingredients do
local ingredient_tier = research_tiers[ingredients[i].name]
tier = ingredient_tier > tier and ingredient_tier or tier
end
return tier
end
local function on_market_purchase(event)
local item = event.item
local name = item.name
local player = event.player
local force = player.force
if name == 'tank' then
player.insert('tank')
game.print({'', '[color=yellow]Warning! ', {'entity-name.' .. name}, ' has been brought by ' .. force.name .. '![/color]'})
return
end
local group_name = event.group_name
local research = force.technologies[name]
if research and research.valid then
research.enabled = true
Retailer.remove_item(group_name, name)
local tier = check_heighest_tier(research)
local tier_name = 'random-tier-' .. tier
if not Retailer.get_items(group_name)[tier_name] then
for _, prototype in pairs(MarketItems) do
if prototype.name == tier_name then
prototype.price = saved_prices[force.name][tier_name]
Retailer.set_item(group_name, prototype)
for _research, _tier in pairs(research_tiers) do
if _tier == tier then
check_random_research_unlock({name = _research, force = force})
end
end
break
end
end
end
end
if item.type == 'random-research' then
random_tech(tonumber(string.sub(item.name, -1)), force, group_name)
end
end
Events.add(Retailer.events.on_market_purchase, on_market_purchase)
local spill_items =
Token.register(
function(data)
data.surface.spill_item_stack(data.position, {name = 'coin', count = data.count}, true)
end
)
local random = math.random
local function invert_force(force)
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
if force == force_USA then
return force_USSR
elseif force == force_USSR then
return force_USA
end
end
local unlock_reasons = {
player_killed = 1,
entity_killed = 2
}
local function unlock_market_item(force, item_name)
local group_name
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
if force == force_USA then
group_name = 'USA_market'
elseif force == force_USSR then
group_name = 'USSR_market'
end
if group_name then
Retailer.enable_item(group_name, item_name)
if not (item_name == 'tank') then
Debug.print('Unlocked: ' .. item_name .. ' | For: ' .. group_name)
end
end
end
local function check_for_market_unlocks(force)
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
for research, conditions in pairs(config.disabled_research) do
local _force = force
local inverted = conditions.invert
local unlocks = conditions.unlocks
if inverted then
_force = invert_force(_force)
end
if force == force_USA then
if conditions.player <= unlock_progress.force_USA.players_killed or conditions.entity <= unlock_progress.force_USA.entities_killed then
unlock_market_item(_force, research)
if unlocks then
unlock_market_item(invert_force(_force), unlocks)
end
end
elseif force == force_USSR then
if conditions.player <= unlock_progress.force_USSR.players_killed or conditions.entity <= unlock_progress.force_USSR.entities_killed then
unlock_market_item(_force, research)
if unlocks then
unlock_market_item(invert_force(_force), unlocks)
end
end
end
end
if force_USA.technologies.tanks.researched then
unlock_market_item(force_USA, 'tank')
end
if force_USSR.technologies.tanks.researched then
unlock_market_item(force_USSR, 'tank')
end
end
local function update_unlock_progress(force, unlock_reason)
local players_killed
local entities_killed
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
if force == force_USA then
players_killed = unlock_progress.force_USA.players_killed
entities_killed = unlock_progress.force_USA.entities_killed
if unlock_reason == unlock_reasons.player_killed then
unlock_progress.force_USA.players_killed = players_killed + 1
elseif unlock_reason == unlock_reasons.entity_killed then
unlock_progress.force_USA.entities_killed = entities_killed + 1
end
elseif force == force_USSR then
players_killed = unlock_progress.force_USSR.players_killed
entities_killed = unlock_progress.force_USSR.entities_killed
if unlock_reason == unlock_reasons.player_killed then
unlock_progress.force_USSR.players_killed = players_killed + 1
elseif unlock_reason == unlock_reasons.entity_killed then
unlock_progress.force_USSR.entities_killed = entities_killed + 1
end
else
return
end
check_for_market_unlocks(force)
end
-- Determines how many coins to drop when enemy entity dies based upon the entity_drop_amount table in config.lua
local function spill_coins(event)
local entity = event.entity
if not entity or not entity.valid then
Debug.print('Entity invalid!')
return
end
if entity.type == 'character' then
return
end
local cause = event.cause
local force = cause and cause.force or event.force
if not force or entity.force == force then
Debug.print('Force invalid for ' .. entity.name)
return
end
local bounds = entity_drop_amount[entity.name]
if not bounds then
Debug.print('No bounds for ' .. entity.name)
return
end
local chance = bounds.chance
if chance == 0 then
Debug.print('Chance 0 for ' .. entity.name)
return
end
if chance == 1 or random() <= chance then
local count = random(bounds.low, bounds.high)
if count > 0 then
Debug.print('Spill ' .. count .. ' coins for ' .. entity.name)
Task.set_timeout_in_ticks(
1,
spill_items,
{
count = count,
surface = entity.surface,
position = entity.position
}
)
end
end
end
local function insert_coins(event)
local entity = event.entity
if entity.type == 'character' then
Debug.print('Character died')
return
end
local force = entity.force
local name = entity.name
if name == 'rocket-silo' then
remote.call('space-race', 'lost', force)
end
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
if force ~= force_USSR and force ~= force_USA then
Debug.print('Not participating forces died')
return
end
local cause = event.cause
local cause_force = event.force
local count = config.entity_kill_rewards[name] or entity_kill_rewards_default
if cause_force then
if cause_force == force then
Debug.print('A friendly did the killing')
return
end
if not (cause_force == force_USA or cause_force == force_USSR) then
Debug.print('Not participating force did the killing, or turrets warming up')
return
end
if not (cause and cause.valid) then
if not (force == force_USA or force == force_USSR) then
Debug.print('Not participating force that died and cause invalid')
return
end
count = math.ceil(count / 2)
Debug.print("Spill " .. count .. " coins")
Task.set_timeout_in_ticks(
1,
spill_items,
{
count = count,
surface = entity.surface,
position = entity.position
}
)
update_unlock_progress(cause_force, unlock_reasons.entity_killed)
return
end
end
if cause and cause.valid then
if cause.prototype.name == 'character' then
cause_force = cause.force
if not (force == cause_force) then
local coins_inserted = cause.insert({name = 'coin', count = count})
local player = cause.player
if player and player.valid then
ScoreTracker.change_for_player(player.index, 'coins-earned', coins_inserted)
update_unlock_progress(cause_force, unlock_reasons.entity_killed)
return
end
Debug.print('Player invalid')
end
Debug.print('Cause and cause_force could be the same')
end
Debug.print('Cause could be something else than character')
end
Debug.print('Reached end without returning')
end
local function on_entity_died(event)
insert_coins(event)
spill_coins(event)
end
Events.add(defines.events.on_entity_died, on_entity_died)
local function on_player_died(event)
local cause = event.cause
local player = game.get_player(event.player_index)
local force = player.force
if cause and cause.valid then
if cause.type == 'character' then
local cause_force = cause.force
if not (force == cause_force) then
local coins_inserted = cause.insert({name = 'coin', count = player_kill_reward})
ScoreTracker.change_for_player(cause.index, 'coins-earned', coins_inserted)
update_unlock_progress(cause_force, unlock_reasons.player_killed)
return
end
end
if cause.force.name == 'enemy' then
Debug.print('Enemy did the killing!')
return
end
if cause.force == force then
Debug.print('Own team did the killing!')
return
end
end
local inverted_force = invert_force(force)
if inverted_force then
Task.set_timeout_in_ticks(
1,
spill_items,
{
count = player_kill_reward,
surface = player.surface,
position = player.position
}
)
update_unlock_progress(inverted_force, unlock_reasons.player_killed)
return
end
end
Events.add(defines.events.on_player_died, on_player_died)
check_random_research_unlock = function(research)
local tier = research_tiers[research.name]
if tier then
local force = research.force
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
local group_name
if force == force_USA then
group_name = 'USA_market'
elseif force == force_USSR then
group_name = 'USSR_market'
end
if group_name then
Retailer.enable_item(group_name, 'random-tier-' .. tier)
end
end
end
local function check_research_tier_finished(tier, force, group_name)
if tier == 7 then
return
end
local tier_name = 'random-tier-' .. tier
local items = Retailer.get_items(group_name)
local item = items[tier_name]
if not item then
return
end
local techs = force.technologies
for _, technology in pairs(techs) do
local in_tier = check_research_tier(technology, tier)
if (in_tier and technology.researched == false and technology.enabled == true) then
return true
end
end
if not saved_prices[force.name] then
saved_prices[force.name] = {}
end
local price = item.price
saved_prices[force.name][tier_name] = price
Retailer.remove_item(group_name, tier_name)
return
end
local function on_research_finished(event)
local research = event.research
local force = research.force
check_for_market_unlocks(force)
check_random_research_unlock(research)
remote.call('space-race', 'remove_recipes')
if not remote.call('space-race', 'get_game_status') then
return
end
local teams = remote.call('space-race', 'get_teams')
local force_USSR = teams[2]
local force_USA = teams[1]
local group_name
if force == force_USA then
group_name = 'USA_market'
elseif force == force_USSR then
group_name = 'USSR_market'
else
return
end
for _, tier in pairs(research_tiers) do
check_research_tier_finished(tier, force, group_name)
end
end
Events.add(defines.events.on_research_finished, on_research_finished)

View File

@ -0,0 +1,145 @@
return {
{
name = 'stone-walls',
name_label = {'', 'Stone Walls research'},
type = 'research',
description = {'', 'Unlocks stone walls research'},
sprite = 'technology/stone-walls',
stack_limit = 1,
price = 50,
disabled = true,
disabled_reason = {'', 'DISABLED'}
},
{
name = 'heavy-armor',
name_label = {'', 'Heavy Armor research'},
type = 'research',
description = {'', 'Unlocks heavy armor research'},
sprite = 'technology/heavy-armor',
stack_limit = 1,
price = 100,
disabled = true,
disabled_reason = {'', 'DISABLED'}
},
{
name = 'military',
name_label = {'', 'Military 1 research'},
type = 'research',
description = {'', 'Unlocks military research'},
sprite = 'technology/military',
stack_limit = 1,
price = 100,
disabled = true,
disabled_reason = {'', 'DISABLED'}
},
{
name = 'military-2',
name_label = {'', 'Military 2 research'},
type = 'research',
description = {'', 'Unlocks military 2 research'},
sprite = 'technology/military-2',
stack_limit = 1,
price = 1500,
disabled = true,
disabled_reason = {'', 'DISABLED'}
},
{
name = 'military-3',
name_label = {'', 'Military 3 research'},
type = 'research',
description = {'', 'Unlocks military 3 research'},
sprite = 'technology/military-3',
stack_limit = 1,
price = 2500,
disabled = true,
disabled_reason = {'', 'DISABLED'}
},
{
name = 'military-4',
name_label = {'', 'Military 4 research'},
type = 'research',
description = {'', 'Unlocks military 4 research'},
sprite = 'technology/military-3',
stack_limit = 1,
price = 5000,
disabled = true,
disabled_reason = {'', 'DISABLED'}
},
{
name = 'tank',
name_label = {'', 'Tank'},
type = 'custom_item',
description = {'', 'Tanks can only be purchased'},
sprite = 'item/tank',
stack_limit = 1,
price = 200,
disabled = true,
disabled_reason = {'', 'Research tanks to unlock'}
},
{price = 10, name = 'raw-fish'},
{price = 10, name = 'repair-pack'},
{
name = 'random-tier-1',
name_label = {'', 'Random Science [item=automation-science-pack]'},
type = 'random-research',
description = {'', 'Purchase a random research with max tier: Automation Science Packs'},
sprite = 'item/automation-science-pack',
stack_limit = 1,
price = 100,
},
{
name = 'random-tier-2',
name_label = {'', 'Random Science [item=logistic-science-pack]'},
type = 'random-research',
description = {'', 'Purchase a random research with max tier: Logistic Science Pack'},
sprite = 'item/logistic-science-pack',
stack_limit = 1,
price = 200,
disabled = true,
disabled_reason = {'', 'Research Logistic Science Pack to unlock'}
},
{
name = 'random-tier-3',
name_label = {'', 'Random Science [item=military-science-pack]'},
type = 'random-research',
description = {'', 'Purchase a random research with max tier: Military Science Pack'},
sprite = 'item/military-science-pack',
stack_limit = 1,
price = 400,
disabled = true,
disabled_reason = {'', 'Research Military Science Pack to unlock'}
},
{
name = 'random-tier-4',
name_label = {'', 'Random Science [item=chemical-science-pack]'},
type = 'random-research',
description = {'', 'Purchase a random research with max tier: Chemical Science Pack'},
sprite = 'item/chemical-science-pack',
stack_limit = 1,
price = 800,
disabled = true,
disabled_reason = {'', 'Research Chemical Science Pack to unlock'}
},
{
name = 'random-tier-5',
name_label = {'', 'Random Science [item=production-science-pack]'},
type = 'random-research',
description = {'', 'Purchase a random research with max tier: Production Science Pack'},
sprite = 'item/production-science-pack',
stack_limit = 1,
price = 1600,
disabled = true,
disabled_reason = {'', 'Research Production Science Pack to unlock'}
},
{
name = 'random-tier-6',
name_label = {'', 'Random Science [item=utility-science-pack]'},
type = 'random-research',
description = {'', 'Purchase a random research with max tier: Utility Science Pack'},
sprite = 'item/utility-science-pack',
stack_limit = 1,
price = 3600,
disabled = true,
disabled_reason = {'', 'Research Utility Science Pack to unlock'}
}
}

View File

@ -0,0 +1,626 @@
local Event = require 'utils.event'
local RS = require 'map_gen.shared.redmew_surface'
local Command = require 'utils.command'
local Color = require 'resources.color_presets'
local Global = require 'utils.global'
local Retailer = require 'features.retailer'
local Market_Items = require 'map_gen.maps.space_race.market_items'
local Token = require 'utils.token'
local Task = require 'utils.task'
local config = require 'map_gen.maps.space_race.config'
local Table = require 'utils.table'
local floor = math.floor
require 'map_gen.maps.space_race.map_info'
require 'map_gen.maps.space_race.market_handler'
local Lobby = require 'map_gen.maps.space_race.lobby'
local cliff = require 'map_gen.maps.space_race.cliff_generator'
-- GUIs
local load_gui = require 'map_gen.maps.space_race.gui.load_gui'
local Public = {}
local redmew_config = global.config
redmew_config.market.enabled = false
redmew_config.score.enabled = false
redmew_config.player_rewards.enabled = false
redmew_config.apocalypse.enabled = false
redmew_config.turret_active_delay.turret_types = {
['ammo-turret'] = 60 * 10,
['electric-turret'] = 60 * 20,
['fluid-turret'] = 60 * 15,
['artillery-turret'] = 60 * 60
}
redmew_config.turret_active_delay.techs = {}
redmew_config.player_create.show_info_at_start = false
redmew_config.camera.enabled = false
local players_needed = config.players_needed_to_start_game
local player_kill_reward = config.player_kill_reward
local startup_timer = config.bootstrap_period
local player_ports = {
USA = {{x = -409, y = 0}, {x = -380, y = 0}},
USSR = {{x = 409, y = 0}, {x = 380, y = 0}}
}
local disabled_research = config.disabled_research
local researched_tech = {}
local disabled_recipes = config.disabled_recipes
local primitives = {
game_started = false,
game_generating = false,
started_tick = nil,
force_USA = nil,
force_USSR = nil,
lobby_permissions = nil,
won = nil
}
Global.register(
{
primitives = primitives
},
function(tbl)
primitives = tbl.primitives
end
)
function Public.remove_recipes()
local USA_recipe = primitives.force_USA.recipes
local USSR_recipe = primitives.force_USSR.recipes
for _, recipe in pairs(disabled_recipes) do
USA_recipe[recipe].enabled = false
USSR_recipe[recipe].enabled = false
end
end
local remove_permission_group =
Token.register(
function(params)
params.permission_group.remove_player(params.player)
end
)
Event.on_init(
function()
game.difficulty_settings.technology_price_multiplier = 0.5
local force_USA = game.create_force('United Factory Workers')
local force_USSR = game.create_force('Union of Factory Employees')
local surface = RS.get_surface()
surface.min_brightness = 0;
force_USSR.set_spawn_position({x = 409, y = 0}, surface)
force_USA.set_spawn_position({x = -409, y = 0}, surface)
force_USSR.laboratory_speed_modifier = 1
force_USA.laboratory_speed_modifier = 1
force_USSR.research_queue_enabled = true
force_USA.research_queue_enabled = true
local lobby_permissions = game.permissions.create_group('lobby')
lobby_permissions.set_allows_action(defines.input_action.start_walking, false)
force_USSR.chart(RS.get_surface(), {{x = 380, y = 64}, {x = 420, y = -64}})
force_USA.chart(RS.get_surface(), {{x = -380, y = 64}, {x = -420, y = -64}})
--game.forces.player.chart(RS.get_surface(), {{x = 400, y = 65}, {x = -400, y = -33}})
local market
market = surface.create_entity {name = 'market', position = {x = 404, y = 0}, force = force_USSR}
market.destructible = false
Retailer.add_market('USSR_market', market)
market = surface.create_entity {name = 'market', position = {x = -404, y = 0}, force = force_USA}
market.destructible = false
Retailer.add_market('USA_market', market)
if table.size(Retailer.get_items('USSR_market')) == 0 then
local items = Table.deep_copy(Market_Items)
for _, prototype in pairs(items) do
local name = prototype.name
prototype.price = (disabled_research[name] and disabled_research[name].player) and disabled_research[name].player * player_kill_reward or prototype.price
local unlock_requires = disabled_research[name]
if prototype.disabled and unlock_requires then
if unlock_requires.invert then
prototype.disabled_reason = {'', 'Unlocks when ' .. unlock_requires.player .. ' players have been killed or\n' .. unlock_requires.entity .. ' entities have been destroyed'}
else
prototype.disabled_reason = {'', 'To unlock kill ' .. unlock_requires.player .. ' players or\ndestroy ' .. unlock_requires.entity .. ' entities'}
end
end
Retailer.set_item('USSR_market', prototype)
end
end
if table.size(Retailer.get_items('USA_market')) == 0 then
local items = Table.deep_copy(Market_Items)
for _, prototype in pairs(items) do
local name = prototype.name
prototype.price = (disabled_research[name] and disabled_research[name].player) and disabled_research[name].player * player_kill_reward or prototype.price
local unlock_requires = disabled_research[name]
if prototype.disabled and unlock_requires then
if unlock_requires.invert then
prototype.disabled_reason = {'', 'Unlocks when ' .. unlock_requires.player .. ' players have been killed or\n ' .. unlock_requires.entity .. ' entities have been destroyed'}
else
prototype.disabled_reason = {'', 'To unlock kill ' .. unlock_requires.player .. ' players or\n destroy ' .. unlock_requires.entity .. ' entities'}
end
end
Retailer.set_item('USA_market', prototype)
end
end
--ensures that the spawn points are not water
surface.set_tiles(
{
{name = 'stone-path', position = {x = 409.5, y = 0.5}},
{name = 'stone-path', position = {x = 409.5, y = -0.5}},
{name = 'stone-path', position = {x = 408.5, y = -0.5}},
{name = 'stone-path', position = {x = 408.5, y = 0.5}},
{name = 'stone-path', position = {x = -409.5, y = 0.5}},
{name = 'stone-path', position = {x = -409.5, y = -0.5}},
{name = 'stone-path', position = {x = -408.5, y = -0.5}},
{name = 'stone-path', position = {x = -408.5, y = 0.5}}
}
)
for force_side, ports in pairs(player_ports) do
local force
if force_side == 'USA' then
force = force_USA
elseif force_side == 'USSR' then
force = force_USSR
end
for _, port in pairs(ports) do
rendering.draw_text {text = {'', 'Use the /warp command to teleport across'}, surface = surface, target = port, color = Color.red, forces = {force}, alignment = 'center', scale = 0.75}
end
end
local USA_tech = force_USA.technologies
local USSR_tech = force_USSR.technologies
for research, _ in pairs(disabled_research) do
USA_tech[research].enabled = false
USSR_tech[research].enabled = false
end
for research, _ in pairs(researched_tech) do
USA_tech[research].researched = true
USSR_tech[research].researched = true
end
primitives.force_USA = force_USA
primitives.force_USSR = force_USSR
primitives.lobby_permissions = lobby_permissions
Public.remove_recipes()
end
)
local function restore_character(player)
if primitives.game_started then
local character = player.character
if character then
character.destroy()
end
player.set_controller {type = defines.controllers.god}
player.create_character()
Task.set_timeout_in_ticks(1, remove_permission_group, {permission_group = primitives.lobby_permissions, player = player})
game.permissions.get_group('Default').add_player(player)
for _, item in pairs(redmew_config.player_create.starting_items) do
player.insert(item)
end
end
end
local tiles = {}
local out_of_map_x = 388
local out_of_map_height = 512
local ignored_height = 18
local insert = table.insert
for i = -out_of_map_height / 2, out_of_map_height / 2, 1 do
if i < -ignored_height / 2 or i > ignored_height / 2 then
insert(tiles, {name = 'out-of-map', position = {x = out_of_map_x + 1, y = i}})
insert(tiles, {name = 'out-of-map', position = {x = -(out_of_map_x + 1), y = i}})
insert(tiles, {name = 'out-of-map', position = {x = out_of_map_x - 1, y = i}})
insert(tiles, {name = 'out-of-map', position = {x = -(out_of_map_x - 1), y = i}})
insert(tiles, {name = 'out-of-map', position = {x = out_of_map_x, y = i}})
insert(tiles, {name = 'out-of-map', position = {x = -(out_of_map_x), y = i}})
end
end
local function generate_structures()
local surface = RS.get_surface()
local force_USSR = primitives.force_USSR
local force_USA = primitives.force_USA
local silo
silo = surface.create_entity {name = 'rocket-silo', position = {x = 388.5, y = -0.5}, force = force_USSR}
silo.minable = false
silo = surface.create_entity {name = 'rocket-silo', position = {x = -388.5, y = 0.5}, force = force_USA}
silo.minable = false
local wall
wall = surface.create_entity {name = 'stone-wall', position = {x = 384.5, y = 18.5}, always_place = true, force = 'neutral'}
wall.destructible = false
wall.minable = false
wall = surface.create_entity {name = 'stone-wall', position = {x = 384.5, y = -17.5}, always_place = true, force = 'neutral'}
wall.destructible = false
wall.minable = false
wall = surface.create_entity {name = 'stone-wall', position = {x = -384.5, y = 18.5}, always_place = true, force = 'neutral'}
wall.destructible = false
wall.minable = false
wall = surface.create_entity {name = 'stone-wall', position = {x = -384.5, y = -17.5}, always_place = true, force = 'neutral'}
wall.destructible = false
wall.minable = false
local gun_turret
gun_turret = surface.create_entity {name = 'gun-turret', position = {x = 383, y = 0}, force = force_USSR}
gun_turret.insert({name = 'firearm-magazine', count = 200})
gun_turret = surface.create_entity {name = 'gun-turret', position = {x = -383, y = 0}, force = force_USA}
gun_turret.insert({name = 'firearm-magazine', count = 200})
end
local function start_game()
primitives.game_started = true
primitives.started_tick = game.tick
game.forces.enemy.evolution_factor = 0
for _, player in pairs(primitives.force_USA.players) do
restore_character(player)
end
for _, player in pairs(primitives.force_USSR.players) do
restore_character(player)
end
local surface = RS.get_surface()
cliff.generate_cliffs(surface)
surface.set_tiles(tiles)
generate_structures()
end
local function victory(force)
primitives.won = force
game.print('Congratulations to ' .. force.name .. '. You have gained factory dominance!')
Lobby.all_to_lobby()
end
function Public.lost(force)
local force_USA = primitives.force_USA
if force == force_USA then
victory(primitives.force_USSR)
else
victory(force_USA)
end
end
local function on_rocket_launched(event)
victory(event.entity.force)
end
Event.add(defines.events.on_rocket_launched, on_rocket_launched)
local function on_built_entity(event)
local entity = event.created_entity
if not entity or not entity.valid then
return
end
local name = entity.name
if config.neutral_entities[name] then
entity.force = 'neutral'
return
end
if config.warning_on_built[name] then
local position = entity.position
game.print({'', '[gps=' .. floor(position.x) .. ', ' .. floor(position.y) .. '] [color=yellow]Warning! ', {'entity-name.' .. name}, ' has been deployed![/color]'})
end
end
Event.add(defines.events.on_built_entity, on_built_entity)
local function allow_teleport(force, position)
if force == primitives.force_USA and position.x > 0 then
return false
elseif force == primitives.force_USSR and position.x < 0 then
return false
end
return math.abs(position.x) > 377 and math.abs(position.x) < 410 and position.y > -10 and position.y < 10
end
local function get_teleport_location(force, to_safe_zone)
local port_number = to_safe_zone and 1 or 2
local position
if force == primitives.force_USA then
position = player_ports.USA[port_number]
elseif force == primitives.force_USSR then
position = player_ports.USSR[port_number]
else
position = {0, 0}
end
local non_colliding_pos = RS.get_surface().find_non_colliding_position('character', position, 6, 1)
position = non_colliding_pos and non_colliding_pos or position
return position
end
local function check_damaged_players()
for k, player in pairs (game.connected_players) do
if player.character and player.character.health ~= nil then
local health_missing = 1 - math.ceil(player.character.health) / (250 + player.character.character_health_bonus)
if health_missing > 0 then
local current_modifier = 0
local hurt_speed_percent = 80
local reduction = 1 - hurt_speed_percent / 100
player.character_running_speed_modifier = (1 - health_missing * reduction) * (current_modifier + 1) - 1
end
end
end
end
Event.on_nth_tick(20, check_damaged_players)
local function teleport(_, player)
local character = player.character
if not character or not character.valid then
player.print('[color=yellow]Could not warp, you are not part of a team yet![/color]')
return
end
local tick = game.tick - primitives.started_tick
if tick < startup_timer then
local time_left = startup_timer - tick
if time_left > 60 then
local minutes = (time_left / 3600)
minutes = minutes - minutes % 1
time_left = time_left - (minutes * 3600)
local seconds = (time_left / 60)
seconds = seconds - seconds % 1
time_left = minutes .. ' minutes and ' .. seconds .. ' seconds left'
else
local seconds = (time_left - (time_left % 60)) / 60
time_left = seconds .. ' seconds left'
end
player.print('[color=yellow]Could not warp, in setup phase![/color] [color=red]' .. time_left .. '[/color]')
return
end
local position = character.position
local force = player.force
if allow_teleport(force, position) then
if math.abs(position.x) < 388.5 then
player.teleport(get_teleport_location(force, true))
else
player.teleport(get_teleport_location(force, false))
end
else
player.print('[color=yellow]Could not warp, you are too far from rocket silo![/color]')
end
end
Command.add('warp', {description = 'Use to switch between PVP and Safe-zone in Space Race', capture_excess_arguments = false, allowed_by_server = false}, teleport)
local check_map_gen_is_done
local start_game_delayed =
Token.register(
function()
if primitives.started_tick == -1 then
primitives.started_tick = 0
load_gui.remove_gui()
Event.remove_removable_nth_tick(60, check_map_gen_is_done)
start_game()
end
end
)
check_map_gen_is_done =
Token.register(
function()
local num_usa_players = #primitives.force_USA.connected_players
local num_ussr_players = #primitives.force_USSR.connected_players
local num_players = num_usa_players + num_ussr_players
if not primitives.game_started and num_players >= players_needed then
local surface = RS.get_surface()
if
primitives.started_tick ~= -1 and surface.get_tile({388.5, 0}).name == 'landfill' and surface.get_tile({-388.5, 0}).name == 'landfill' and surface.get_tile({388.5, 60}).name == 'out-of-map' and surface.get_tile({-388.5, 60}).name == 'out-of-map' and
surface.get_tile({-479.5, 0}).name == 'water' and
surface.get_tile({479.5, 0}).name == 'water'
then
primitives.started_tick = -1
game.print('[color=yellow]Game starts in 10 seconds![/color]')
Task.set_timeout_in_ticks(599, start_game_delayed, {})
end
load_gui.show_gui_to_all()
else
primitives.started_tick = nil
load_gui.remove_gui()
Event.remove_removable_nth_tick(60, check_map_gen_is_done)
end
end
)
local function check_ready_to_start()
if primitives.game_started then
return
end
local num_usa_players = #primitives.force_USA.connected_players
local num_ussr_players = #primitives.force_USSR.connected_players
local num_players = num_usa_players + num_ussr_players
if not primitives.game_started and num_players >= players_needed then
if primitives.started_tick == nil then
primitives.started_tick = game.tick
Event.add_removable_nth_tick(60, check_map_gen_is_done)
end
else
local message = primitives.force_USA.name .. ' has ' .. num_usa_players .. ' players\n ' .. primitives.force_USSR.name .. ' has ' .. num_ussr_players .. ' players\n\n' .. players_needed - num_players .. ' more players needed to start!'
load_gui.show_gui_to_all(message)
end
end
local function check_player_balance(force)
local force_USSR = primitives.force_USSR
local force_USA = primitives.force_USA
--local usa_players = #force_USA.players
--local ussr_players = #force_USSR.players
local usa_connected = #force_USA.connected_players
local ussr_connected = #force_USSR.connected_players
if force == force_USSR then
--return ussr_players - 2 <= usa_players and ussr_connected <= usa_connected
return usa_connected - ussr_connected
elseif force == force_USA then
-- return ussr_players >= usa_players - 2 and ussr_connected >= usa_connected
return ussr_connected - usa_connected
end
end
function Public.join_usa(_, player)
local force_USA = primitives.force_USA
local force_USSR = primitives.force_USSR
local force = player.force
local balance = check_player_balance(force_USA)
local allow_switching_team = balance >= 2
if balance < 0 then
player.print('[color=red]Failed to join [/color][color=yellow]United Factory Workers,[/color][color=red] teams would become unbalanced![/color]')
return false
end
if not primitives.game_started or (force ~= force_USSR and force ~= force_USA) or allow_switching_team then
if force == force_USA then
player.print('[color=red]Failed to join [/color][color=yellow]United Factory Workers,[/color][color=red] you are already part of this team![/color]')
return false
end
if allow_switching_team and player.character then
local empty_inventory =
player.get_inventory(defines.inventory.character_main).is_empty() and
player.get_inventory(defines.inventory.character_trash).is_empty() and
player.get_inventory(defines.inventory.character_ammo).is_empty() and
player.get_inventory(defines.inventory.character_armor).is_empty() and
player.get_inventory(defines.inventory.character_guns).is_empty() and
player.crafting_queue_size == 0
if not empty_inventory then
player.print('[color=red]Failed to join [/color][color=yellow]United Factory Workers,[/color][color=red] you need an empty inventory![/color]')
return false
end
end
player.force = force_USA
player.print('[color=green]You have joined United Factory Workers![/color]')
restore_character(player)
player.teleport(get_teleport_location(force_USA, true), RS.get_surface())
check_ready_to_start()
remote.call('space-race-lobby', 'update_gui')
return true
end
player.print('Failed to join new team, do not be a spy!')
end
Command.add('join-UFW', {description = 'Use to join United Factory Workers in Space Race', capture_excess_arguments = false, allowed_by_server = false}, Public.join_usa)
function Public.join_ussr(_, player)
local force_USA = primitives.force_USA
local force_USSR = primitives.force_USSR
local force = player.force
local balance = check_player_balance(force_USSR)
local allow_switching_team = balance >= 2
if balance < 0 then
player.print('[color=red]Failed to join [/color][color=yellow]Union of Factory Employees[/color][color=red], teams would become unbalanced![/color]')
return false
end
if not primitives.game_started or (force ~= force_USSR and force ~= force_USA) or allow_switching_team then
if force == force_USSR then
player.print('[color=red]Failed to join [/color][color=yellow]United Factory Workers,[/color][color=red] you are already part of this team![/color]')
return false
end
if allow_switching_team and player.character then
local empty_inventory =
player.get_inventory(defines.inventory.character_main).is_empty() and
player.get_inventory(defines.inventory.character_trash).is_empty() and
player.get_inventory(defines.inventory.character_ammo).is_empty() and
player.get_inventory(defines.inventory.character_armor).is_empty() and
player.get_inventory(defines.inventory.character_guns).is_empty() and
player.crafting_queue_size == 0
if not empty_inventory then
player.print('[color=red]Failed to join [/color][color=yellow]United Factory Workers,[/color][color=red] you need an empty inventory![/color]')
return false
end
end
player.force = force_USSR
player.print('[color=green]You have joined Union of Factory Employees![/color]')
restore_character(player)
player.teleport(get_teleport_location(force_USSR, true), RS.get_surface())
check_ready_to_start()
remote.call('space-race-lobby', 'update_gui')
return true
end
player.print('Failed to join new team, do not be a spy!')
end
Command.add('join-UFE', {description = 'Use to join Union of Factory Employees in Space Race', capture_excess_arguments = false, allowed_by_server = false}, Public.join_ussr)
local function print_player_num(_, player)
local force_USA = primitives.force_USA
local force_USSR = primitives.force_USSR
player.print('West: ' .. #force_USA.connected_players .. ' online /' .. #force_USA.players .. ' total')
player.print('East: ' .. #force_USSR.connected_players .. ' online /' .. #force_USSR.players .. ' total')
end
Command.add('team_players', {description = 'Use to get number of players on both teams', capture_excess_arguments = false, allowed_by_server = false}, print_player_num)
function Public.get_won()
return primitives.won
end
function Public.get_teams()
return {primitives.force_USA, primitives.force_USSR}
end
function Public.get_game_status()
return primitives.game_started
end
function Public.get_started_tick()
return primitives.started_tick
end
remote.add_interface('space-race', Public)
--[[TODO
Starting trees!
NOTES:
Mapgen is slow (a loading screen would be nice)
Tiny islands in shallow water, space for a couple of turrets but not much
Weapon damage balance -> Testing, testing, testing
]]

View File

@ -6,7 +6,7 @@ local insert = table.insert
local tiles_per_tick
local regen_decoratives
local surfaces
local surfaces = {}
local total_calls
@ -282,7 +282,9 @@ end
function Public.init(args)
tiles_per_tick = args.tiles_per_tick or 32
regen_decoratives = args.regen_decoratives or false
surfaces = args.surfaces or {}
for surface_name, shape in pairs(args.surfaces or {}) do
surfaces[surface_name] = shape
end
total_calls = math.ceil(1024 / tiles_per_tick) + 5
end
@ -312,8 +314,12 @@ function Public.register()
end
--- Returns the surfaces that the generate functions will act on
-- Warning! Changing this table after on_init or on_load has run will cause desyncs!
-- @return dictionary of surface_name -> shape function
function Public.get_surfaces()
if _LIFECYCLE == 8 then
error('Calling Generate.get_surfaces after on_init() or on_load() has run is a desync risk.', 2)
end
return surfaces
end

View File

@ -7,7 +7,7 @@ local counter = 0
--- Assigns a unquie id for the given var.
-- This function cannot be called after on_init() or on_load() has run as that is a desync risk.
-- Typically this is used to register functions, so the id can be stored in the global table
-- instead of the function. This is becasue closures cannot be safely stored in the global table.
-- instead of the function. This is because closures cannot be safely stored in the global table.
-- @param var<any>
-- @return number the unique token for the variable.
function Token.register(var)