1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-03-17 21:08:08 +02:00

Changed all windows style line endings to unix style line endings (#393)

This commit is contained in:
Valansch 2018-11-18 17:12:00 +01:00 committed by GitHub
parent bdfd122f3c
commit 7fa48bc583
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 5338 additions and 5336 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*.lua text eol=lf
*.md text eol=lf

View File

@ -1,6 +1,6 @@
## RedMew Documentation Index
- [Installing and Using the RedMew Scenario](Installation.md)
- [Creating a New Scenario Using the RedMew Framework](NewScenario.md)
### Scenario Specific Documentation
- [Diggy Installation and Configuration](scenarios/Diggy.md)
## RedMew Documentation Index
- [Installing and Using the RedMew Scenario](Installation.md)
- [Creating a New Scenario Using the RedMew Framework](NewScenario.md)
### Scenario Specific Documentation
- [Diggy Installation and Configuration](scenarios/Diggy.md)

View File

@ -1,49 +1,49 @@
## Installing and Using the RedMew Scenario
Some scenarios have more detailed information, please check [the index](Index.md) before continuing with the generic
RedMew installation. To install the RedMew scenario directly into something playable, [download the
archive](https://github.com/Valansch/RedMew/archive/develop.zip) and take the next step based on your Operating System.
- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\RedMew`
- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/RedMew`
- **Linux**: extract the the zip file into `~/.factorio/scenarios/RedMew`
Make sure it's called RedMew and there's a `control.lua` in the root of that directory. If you are using the RedMew
scenario for a public-facing multi-player server, be sure to provide attribution back to github and keep links to the
Discord, Patreon and website intact.
> _Note_: these locations are based on the default configuration [defined by
factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
scenarios directory in another way.
## Generating maps
There are 3 ways to generate maps using our scenario: Vanilla, FactorioMapConverter and Custom Maps.
### Vanilla
Start the scenario from the scenario menu and you are ready to go. Additionally you can turn features on or off via
[`control.lua`](../control.lua) if desired.
### Custom Maps
There are many pre-made map modules that can be combined to create a unique map.
Map module previews can be found in [map_gen/data/.map_previews](../map_gen/data/.map_previews). You can select and
activate a module by removing the `--` in front of the require in [`map_layout.lua`](../map_layout.lua).
You can mix as many modules as you want, as long as they logically fit together.
### FactorioMapConverter (Windows only)
You can generate your own maps from images. First convert the image file into a lua file (For example `image_data.lua`).
Then use our scenario to load the `image_data.lua` file and generate the map from it.
To create your own map preview:
1. Download the Map Converter [here](https://github.com/grilledham/FactorioMapConverter/releases) to generate the
`image_data.lua`.
2. Place your `image_data.lua` file in the `map_gen/data/presets/` directory.
3. Create new lua file (for example `my_image.lua`) inside the folder `map_gen/presets/`. This file is used to configure
your map (scale, translate etc.). To do this, you can copy `map_gen/presets/template.lua` and replace line 8 to point
to your `image_data.lua`
4. Load your new preset by adding a new line to `map_layout.lua`. This should look similar to this:
```lua
MAP_GEN = require "map_gen.presets.my_image.lua"
```
5. Load the scenario from the scenario menu.
## Installing and Using the RedMew Scenario
Some scenarios have more detailed information, please check [the index](Index.md) before continuing with the generic
RedMew installation. To install the RedMew scenario directly into something playable, [download the
archive](https://github.com/Valansch/RedMew/archive/develop.zip) and take the next step based on your Operating System.
- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\RedMew`
- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/RedMew`
- **Linux**: extract the the zip file into `~/.factorio/scenarios/RedMew`
Make sure it's called RedMew and there's a `control.lua` in the root of that directory. If you are using the RedMew
scenario for a public-facing multi-player server, be sure to provide attribution back to github and keep links to the
Discord, Patreon and website intact.
> _Note_: these locations are based on the default configuration [defined by
factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
scenarios directory in another way.
## Generating maps
There are 3 ways to generate maps using our scenario: Vanilla, FactorioMapConverter and Custom Maps.
### Vanilla
Start the scenario from the scenario menu and you are ready to go. Additionally you can turn features on or off via
[`control.lua`](../control.lua) if desired.
### Custom Maps
There are many pre-made map modules that can be combined to create a unique map.
Map module previews can be found in [map_gen/data/.map_previews](../map_gen/data/.map_previews). You can select and
activate a module by removing the `--` in front of the require in [`map_layout.lua`](../map_layout.lua).
You can mix as many modules as you want, as long as they logically fit together.
### FactorioMapConverter (Windows only)
You can generate your own maps from images. First convert the image file into a lua file (For example `image_data.lua`).
Then use our scenario to load the `image_data.lua` file and generate the map from it.
To create your own map preview:
1. Download the Map Converter [here](https://github.com/grilledham/FactorioMapConverter/releases) to generate the
`image_data.lua`.
2. Place your `image_data.lua` file in the `map_gen/data/presets/` directory.
3. Create new lua file (for example `my_image.lua`) inside the folder `map_gen/presets/`. This file is used to configure
your map (scale, translate etc.). To do this, you can copy `map_gen/presets/template.lua` and replace line 8 to point
to your `image_data.lua`
4. Load your new preset by adding a new line to `map_layout.lua`. This should look similar to this:
```lua
MAP_GEN = require "map_gen.presets.my_image.lua"
```
5. Load the scenario from the scenario menu.

View File

@ -1,28 +1,28 @@
## Creating a New Scenario Using the RedMew Framework
To add a new scenario and make it available to everyone that wants to use RedMew, make a Pull Request on github to
request adding your scenario to the repository.
### Starting From Scratch
Depending on the size of the scenario, it could be desired to have its own dedicated directory. By default a scenario
is added in `map_gen/combined/your_scenario.lua`.
#### Step 1
If you're not experienced with git, it's advised to read up on how git works first or ask someone else to help out. To
get your change into the repository, you need to [fork the repository](https://help.github.com/articles/fork-a-repo/)
and eventually make your Pull Request from there. [Clone](https://help.github.com/articles/cloning-a-repository/) the
fork to your local environment and get your favorite IDE or Editor ready.
#### Step 2
Small scenarios can go into a single lua file, bigger scenarios might need their own dedicated directory. To follow the
RedMew structure for scenarios, create your scenario file: `map_gen/combined/your_scenario_file.lua`.
#### Step 3 (Optional)
If you plan on making a bigger scenario, create a directory: `map_gen/combined/your_scenario_file/` where you can place
your scenario specific lua files.
#### Step 4
Regardless, the `map_gen/combined/your_scenario_file.lua` file will be the entry point for your scenario and will be
loaded via `map_layout.lua`. Underneath `--combined--`, add your require: `require map_gen.combined.your_scenario_file`.
When making the Pull Request, make sure to comment the require in `map_layout.lua` as by default it should be off. To
enable debugging and get some extra feedback during development, enable `_DEBUG` in `config.lua`.
## Creating a New Scenario Using the RedMew Framework
To add a new scenario and make it available to everyone that wants to use RedMew, make a Pull Request on github to
request adding your scenario to the repository.
### Starting From Scratch
Depending on the size of the scenario, it could be desired to have its own dedicated directory. By default a scenario
is added in `map_gen/combined/your_scenario.lua`.
#### Step 1
If you're not experienced with git, it's advised to read up on how git works first or ask someone else to help out. To
get your change into the repository, you need to [fork the repository](https://help.github.com/articles/fork-a-repo/)
and eventually make your Pull Request from there. [Clone](https://help.github.com/articles/cloning-a-repository/) the
fork to your local environment and get your favorite IDE or Editor ready.
#### Step 2
Small scenarios can go into a single lua file, bigger scenarios might need their own dedicated directory. To follow the
RedMew structure for scenarios, create your scenario file: `map_gen/combined/your_scenario_file.lua`.
#### Step 3 (Optional)
If you plan on making a bigger scenario, create a directory: `map_gen/combined/your_scenario_file/` where you can place
your scenario specific lua files.
#### Step 4
Regardless, the `map_gen/combined/your_scenario_file.lua` file will be the entry point for your scenario and will be
loaded via `map_layout.lua`. Underneath `--combined--`, add your require: `require map_gen.combined.your_scenario_file`.
When making the Pull Request, make sure to comment the require in `map_layout.lua` as by default it should be off. To
enable debugging and get some extra feedback during development, enable `_DEBUG` in `config.lua`.

View File

@ -1,79 +1,79 @@
## Diggy Installation and Configuration
Diggy is a custom [RedMew](../../README.md) scenario. You start out with nothing but a market, your pick-axe and some
walls [deep, deep in the mine](https://www.youtube.com/watch?v=ov5pxaIbJlM). The goal is to launch a rocket, but be
careful, there's not a lot of space and the mine is unstable!
- Gameplay: https://www.youtube.com/watch?v=J3lheDK-6Cw
- Time lapse video: https://www.youtube.com/watch?v=4cRsx-wl_fk (By Namelesshunter Gaming)
> _Note_: Scenarios- also known as soft-mods- are scripted maps. They can be played online without having to download
any mods as the script is included in the map.
### Scenario Information
The idea of Diggy is similar to vanilla, except that it greatly changes how to build your factory. As you're in a cave,
each rock you dig, each support entity you remove and every tile you mine, can cause a collapse. You can use walls,
stone paths and (refined) concrete floor to increase the strength of your mine and reduce the chance of a collapse.
Whenever you place or remove a wall for example, the stress level of the area around it (9x9 tiles) will rise or lower.
When a certain threshold is reached, the cave will collapse. You can stop this by quickly placing walls or run away as
fast as you can. Letting the cave collapse _will_ destroy structures below it! The recommended pattern on dirt is to
place a wall every 4th tile. Using stone paths and concrete will increase this to 5 tiles while refined concrete will
make it 6.
## How to start Diggy for Single-player mode
#### Step 1
Download the zip file from
[https://github.com/Valansch/RedMew/archive/develop.zip](https://github.com/Valansch/RedMew/archive/develop.zip)
#### Step 2
- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\Diggy`
- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/Diggy`
- **Linux**: extract the the zip file into `~/.factorio/scenarios/Diggy`
Make sure it's called Diggy and there's a `control.lua` in the root of that directory.
> _Note_: these locations are based on the default configuration [defined by
factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
scenarios directory in another way.
#### Step 3
Open `map_layout.lua` in that directory and look for `--require "map_gen.combined.diggy"`.
Change this to `require "map_gen.combined.diggy"`, by removing the double dashes.
#### Step 4
In factorio start either a local or online game via Scenarios. Select `Diggy` under
`User scenarios` and start it up.
> _Note:_ Downloading the latest version might not always be a functional version, please consult on discord for a
working version if this is the case.
#### Step 5 (optional)
Diggy is designed to work for at least 15 players online, working together. It's advised to change the configuration
to adjust the difficulty for your needs. You can find the config in `map_gen/Diggy/Config.lua`. Most options should be
well-explained. For Single-player it's recommend to enable cheats with modified values. You can change the starting
items and some pre-defined cheat values (if cheats are enabled) under the `SetupPlayer` config item.
## Configuring Diggy
### Changing or Disabling Biter Spawning
You can find the biter spawning feature in the config file under `AlienSpawner`. If you don't want biters to spawn
according to the Diggy scenario, turn this feature off completely.
### Disabling Collapses
While one of the core features, it can also be fun to play without. To turn off collapses completely, you can turn off
this feature under `DiggyCaveCollapse`. If you experience performance issues while digging, you can turn off this
feature as well as it can be quite heavy.
### Configuring Resource Spawning
At the moment, Diggy is not yet using any of the build-in mechanics to spawn resources and you will have to manually add
them. The resource spawning mechanism is quite complex, so don't hesitate to us how to configure it on Discord. Most
basic configuration can be found under `ScatteredResources`. To customize the resource weights, you have to configure
those specifics in the `map_gen/Diggy/Orepattern` directory. Resources are defined with a weight, meaning you can add
your own resources (for example bobs or angels) with a value and the scenario will automatically calculate the proper
spawn chances.
### Adding Market Items
Items can be configured by adding the desired item under the `MarketExchange` configuration. You only have to define a
level at which it unlocks, a price or prices in case it can cost more, and what the item prototype is. For a list of
items, you can look up each possible item on the [Factorio raw data page](https://wiki.factorio.com/Data.raw#item).
## Diggy Installation and Configuration
Diggy is a custom [RedMew](../../README.md) scenario. You start out with nothing but a market, your pick-axe and some
walls [deep, deep in the mine](https://www.youtube.com/watch?v=ov5pxaIbJlM). The goal is to launch a rocket, but be
careful, there's not a lot of space and the mine is unstable!
- Gameplay: https://www.youtube.com/watch?v=J3lheDK-6Cw
- Time lapse video: https://www.youtube.com/watch?v=4cRsx-wl_fk (By Namelesshunter Gaming)
> _Note_: Scenarios- also known as soft-mods- are scripted maps. They can be played online without having to download
any mods as the script is included in the map.
### Scenario Information
The idea of Diggy is similar to vanilla, except that it greatly changes how to build your factory. As you're in a cave,
each rock you dig, each support entity you remove and every tile you mine, can cause a collapse. You can use walls,
stone paths and (refined) concrete floor to increase the strength of your mine and reduce the chance of a collapse.
Whenever you place or remove a wall for example, the stress level of the area around it (9x9 tiles) will rise or lower.
When a certain threshold is reached, the cave will collapse. You can stop this by quickly placing walls or run away as
fast as you can. Letting the cave collapse _will_ destroy structures below it! The recommended pattern on dirt is to
place a wall every 4th tile. Using stone paths and concrete will increase this to 5 tiles while refined concrete will
make it 6.
## How to start Diggy for Single-player mode
#### Step 1
Download the zip file from
[https://github.com/Valansch/RedMew/archive/develop.zip](https://github.com/Valansch/RedMew/archive/develop.zip)
#### Step 2
- **Windows**: extract the the zip file into `%appdata%\Factorio\Scenarios\Diggy`
- **MacOS**: extract the the zip file into `~/Library/Application Support/factorio/Scenarios/Diggy`
- **Linux**: extract the the zip file into `~/.factorio/scenarios/Diggy`
Make sure it's called Diggy and there's a `control.lua` in the root of that directory.
> _Note_: these locations are based on the default configuration [defined by
factorio](https://wiki.factorio.com/Application_directory). If your installation is not default, you have to find your
scenarios directory in another way.
#### Step 3
Open `map_layout.lua` in that directory and look for `--require "map_gen.combined.diggy"`.
Change this to `require "map_gen.combined.diggy"`, by removing the double dashes.
#### Step 4
In factorio start either a local or online game via Scenarios. Select `Diggy` under
`User scenarios` and start it up.
> _Note:_ Downloading the latest version might not always be a functional version, please consult on discord for a
working version if this is the case.
#### Step 5 (optional)
Diggy is designed to work for at least 15 players online, working together. It's advised to change the configuration
to adjust the difficulty for your needs. You can find the config in `map_gen/Diggy/Config.lua`. Most options should be
well-explained. For Single-player it's recommend to enable cheats with modified values. You can change the starting
items and some pre-defined cheat values (if cheats are enabled) under the `SetupPlayer` config item.
## Configuring Diggy
### Changing or Disabling Biter Spawning
You can find the biter spawning feature in the config file under `AlienSpawner`. If you don't want biters to spawn
according to the Diggy scenario, turn this feature off completely.
### Disabling Collapses
While one of the core features, it can also be fun to play without. To turn off collapses completely, you can turn off
this feature under `DiggyCaveCollapse`. If you experience performance issues while digging, you can turn off this
feature as well as it can be quite heavy.
### Configuring Resource Spawning
At the moment, Diggy is not yet using any of the build-in mechanics to spawn resources and you will have to manually add
them. The resource spawning mechanism is quite complex, so don't hesitate to us how to configure it on Discord. Most
basic configuration can be found under `ScatteredResources`. To customize the resource weights, you have to configure
those specifics in the `map_gen/Diggy/Orepattern` directory. Resources are defined with a weight, meaning you can add
your own resources (for example bobs or angels) with a value and the scenario will automatically calculate the proper
spawn chances.
### Adding Market Items
Items can be configured by adding the desired item under the `MarketExchange` configuration. You only have to define a
level at which it unlocks, a price or prices in case it can cost more, and what the item prototype is. For a list of
items, you can look up each possible item on the [Factorio raw data page](https://wiki.factorio.com/Data.raw#item).

View File

@ -1,360 +1,360 @@
local Module = {}
local Gui = require("utils.gui")
local Utils = require("utils.utils");
local Game = require 'utils.game'
local report_frame_name = Gui.uid_name()
local report_close_button_name = Gui.uid_name()
local report_tab_button_name = Gui.uid_name()
local jail_offender_button_name = Gui.uid_name()
local report_body_name = Gui.uid_name()
local prefix = '------------------NOTICE-------------------'
local prefix_e = '--------------------------------------------'
global.reports = {}
global.player_report_data = {}
local function draw_report(parent, report_id)
local report = global.reports[report_id]
if report_id == 0 or not report then
parent.add {type = "label", caption="No reports yet."}
return
end
local reported_player_name = Game.get_player_by_index(report.reported_player_index).name
local reporting_player_name = "<script>"
if report.reporting_player_index then
reporting_player_name = Game.get_player_by_index(report.reporting_player_index).name
end
local time = Utils.format_time(report.tick)
local time_ago = Utils.format_time(game.tick - report.tick)
local message = report.message
Gui.clear(parent)
parent.add {type="label", caption="Offender: " .. reported_player_name}
local msg_label_pane = parent.add {type="scroll-pane", vertical_scroll_policy = "auto-and-reserve-space", horizontal_scroll_policy="never"}
msg_label_pane.style.maximal_height = 400
local msg_label = msg_label_pane.add {type="label", caption="Message: " .. message}
local jail_offender_button = parent.add {type = 'button', name = jail_offender_button_name, caption = 'Jail ' .. reported_player_name}
jail_offender_button.style.height = 24
jail_offender_button.style.font = 'default-small'
jail_offender_button.style.top_padding = 0
jail_offender_button.style.bottom_padding = 0
jail_offender_button.style.left_padding = 0
jail_offender_button.style.right_padding = 0
msg_label.style.single_line = false
msg_label.style.maximal_width = 680
parent.add {type="label", caption=string.format("Time: %s (%s ago)", time, time_ago)}
parent.add {type="label", caption="Reported by: " .. reporting_player_name}
end
Module.show_reports = function(player)
local reports = global.reports or {}
local center = player.gui.center
local report_frame = center[report_frame_name]
if report_frame and report_frame.valid then
Gui.destroy(report_frame)
end
report_frame = center.add {
type = 'frame',
name = report_frame_name,
direction = 'vertical',
caption = 'User reports'
}
report_frame.style.maximal_width = 700
player.opened = report_frame
if #reports > 1 then
local scroll_pane = report_frame.add{type = "scroll-pane", horizontal_scroll_policy = "auto-and-reserve-space", vertical_scroll_policy="never"}
local tab_flow = scroll_pane.add{type="flow"}
for k,report in pairs(reports) do
local button_cell = tab_flow.add{type="flow", caption="reportuid" .. k}
button_cell.add {
type="button",
name=report_tab_button_name,
caption = Game.get_player_by_index(report.reported_player_index).name
}
end
end
local report_body = report_frame.add {type = "scroll-pane", name = report_body_name, horizontal_scroll_policy = "never", vertical_scroll_policy="never"}
report_frame.add {type = 'button', name = report_close_button_name, caption = 'Close'}
draw_report(report_body, #reports)
end
function Module.report(reporting_player, reported_player, message)
local player_index
if reporting_player then
player_index = reporting_player.index
end
table.insert(global.reports, {reporting_player_index = player_index, reported_player_index = reported_player.index, message = message, tick = game.tick})
local notified = false
for _,p in pairs(game.players) do
if p.admin and p.connected then
p.play_sound{path='utility/tutorial_notice', volume_modifier = 1}
Module.show_reports(p)
if p.afk_time < 3600 then notified = true end
end
end
if not notified then
for _,p in pairs(game.players) do
if p.admin then
Module.show_reports(p)
end
end
end
end
function Module.cmd_report(cmd)
local reporting_player = game.player
if reporting_player then
local params = {}
for param in string.gmatch(cmd.parameter, '%S+') do
table.insert(params, param)
end
if #params < 2 then
reporting_player.print('Please enter then name of the offender and the reason for the report.')
return nil
end
local reported_player_name = params[1] or ''
local reported_player = game.players[reported_player_name]
if not reported_player then
reporting_player.print(reported_player_name .. ' does not exist.')
return nil
end
Module.report(reporting_player, reported_player, string.sub(cmd.parameter, string.len(params[1]) + 2))
end
end
-- Places a target in jail as long as player is admin or server
function Module.jail(target_player, player)
-- Set the name of the jail permission group
local jail_name = 'Jail'
local print
local jailed_by
if player then
jailed_by = "a server admin"
print = player.print
else
jailed_by = "script for causing too many collapses"
print = log
end
if not target_player then
print('Unknown player.')
return
end
local permissions = game.permissions
-- Check if the permission group exists, if it doesn't, create it.
local permission_group = permissions.get_group(jail_name)
if not permission_group then
permission_group = permissions.create_group(jail_name)
end
if target_player.permission_group == permission_group then
print('Player ' .. target_player.name .. ' is already in jail.')
return
end
-- Set all permissions to disabled
for action_name, _ in pairs(defines.input_action) do
permission_group.set_allows_action(defines.input_action[action_name], false)
end
-- Enable writing to console to allow a person to speak
permission_group.set_allows_action(defines.input_action.write_to_console, true)
permission_group.set_allows_action(defines.input_action.edit_permission_group, true)
-- Kick player out of vehicle
target_player.driving=false
-- Add player to jail group
permission_group.add_player(target_player)
-- If a player is shooting when they're jailed they can't stop shooting, so we change their shooting state
if target_player.shooting_state.state ~= 0 then
target_player.shooting_state.state = {state = defines.shooting.not_shooting, position = {0,0}}
end
-- Check that it worked
if target_player.permission_group == permission_group then
-- Let admin know it worked, let target know what's going on.
print(target_player.name .. ' has been jailed. They have been advised of this.')
target_player.print(prefix)
target_player.print('You have been placed in jail by ' .. jailed_by .. '. The only action avaliable to you is chatting.')
target_player.print('Please respond to inquiries from the admins.', {r = 1, g = 1, b = 0, a = 1})
Utils.print_admins(target_player.name .. 'has been jailed by' .. player.name)
Utils.log_command(player, 'jail', target_player.name)
else
-- Let admin know it didn't work.
print('Something went wrong in the jailing of ' .. target_player.name .. '. You can still change their group via /permissions.')
end
end
function Module.unjail_player(cmd)
local default_group = 'Default'
local player = game.player
-- Check if the player can run the command
if player and not player.admin then
Utils.cant_run(cmd.name)
return
end
-- Check if the target is valid (copied from the invoke command)
local target = cmd['parameter']
if target == nil then
Game.player_print('Usage: /unjail <player>')
return
end
local target_player = game.players[target]
if not target_player then
Game.player_print('Unknown player.')
return
end
local permissions = game.permissions
-- Check if the permission group exists, if it doesn't, create it.
local permission_group = permissions.get_group(default_group)
if not permission_group then
permission_group = permissions.create_group(default_group)
end
local jail_permission_group = permissions.get_group('Jail')
if (not jail_permission_group) or target_player.permission_group ~= jail_permission_group then
Game.player_print('The player ' .. target .. ' is already not in Jail.')
return
end
-- Move player
permission_group.add_player(target)
-- Set player to a non-shooting state (solves a niche case where players jailed while shooting will be locked into a shooting state)
target_player.shooting_state.state = 0
-- Check that it worked
if target_player.permission_group == permission_group then
-- Let admin know it worked, let target know what's going on.
Game.player_print(target .. ' has been returned to the default group. They have been advised of this.')
target_player.print(prefix)
target_player.print('Your ability to perform actions has been restored', {r = 0, g = 1, b = 0, a = 1})
target_player.print(prefix_e)
else
-- Let admin know it didn't work.
Game.player_print(
'Something went wrong in the unjailing of ' ..
target .. '. You can still change their group via /permissions and inform them.'
)
end
end
Gui.on_custom_close(
report_frame_name,
function(event)
Gui.destroy(event.element)
end
)
Gui.on_click(
report_close_button_name,
function(event)
Gui.destroy(event.element.parent)
end
)
Gui.on_click(
jail_offender_button_name,
function(event)
local target_name = string.sub(event.element.caption, 6)
local target = game.players[target_name]
Module.jail(target, event.player)
end
)
Gui.on_click(
report_tab_button_name,
function(event)
local center = event.player.gui.center
local report_frame = center[report_frame_name]
local report_uid_str = string.sub(event.element.parent.caption, 10)
local report_uid = tonumber(report_uid_str)
draw_report(report_frame[report_body_name], report_uid)
end
)
local reporting_popup_name = Gui.uid_name()
local reporting_cancel_button_name = Gui.uid_name()
local reporting_submit_button_name = Gui.uid_name()
local reporting_input_name = Gui.uid_name()
Module.spawn_reporting_popup = function(player, reported_player)
local center = player.gui.center
local reporting_popup = center[reporting_popup_name]
if reporting_popup and reporting_popup.valid then
Gui.destroy(reporting_popup)
end
reporting_popup = center.add {
type = 'frame',
name = reporting_popup_name,
direction = 'vertical',
caption = 'Report player ' .. reported_player.name
}
Gui.set_data(reporting_popup, {reported_player_index = reported_player.index})
reporting_popup.style.maximal_width = 500
player.opened = reporting_popup
reporting_popup.add {
type = 'label',
caption = 'Report message:'
}
local input = reporting_popup.add {type = 'text-box', name=reporting_input_name}
input.style.width = 400
input.style.height = 85
local button_flow = reporting_popup.add {type = "flow"}
button_flow.add {type = "button", name = reporting_submit_button_name, caption="Submit"}
button_flow.add {type = "button", name = reporting_cancel_button_name, caption="Cancel"}
end
Gui.on_custom_close(
reporting_popup_name,
function(event)
Gui.destroy(event.element)
end
)
Gui.on_click(
reporting_cancel_button_name,
function(event)
local frame = event.element.parent.parent
Gui.destroy(frame)
end
)
Gui.on_click(
reporting_submit_button_name,
function(event)
local frame = event.element.parent.parent
local msg = frame[reporting_input_name].text
local data = Gui.get_data(frame)
local reported_player_index = data["reported_player_index"]
local print = event.player.print
Gui.destroy(frame)
Module.report(event.player, Game.get_player_by_index(reported_player_index), msg)
print(prefix)
print("You have successfully reported the player: " .. Game.get_player_by_index(reported_player_index).name)
print(prefix_e)
end
)
return Module
local Module = {}
local Gui = require("utils.gui")
local Utils = require("utils.utils");
local Game = require 'utils.game'
local report_frame_name = Gui.uid_name()
local report_close_button_name = Gui.uid_name()
local report_tab_button_name = Gui.uid_name()
local jail_offender_button_name = Gui.uid_name()
local report_body_name = Gui.uid_name()
local prefix = '------------------NOTICE-------------------'
local prefix_e = '--------------------------------------------'
global.reports = {}
global.player_report_data = {}
local function draw_report(parent, report_id)
local report = global.reports[report_id]
if report_id == 0 or not report then
parent.add {type = "label", caption="No reports yet."}
return
end
local reported_player_name = Game.get_player_by_index(report.reported_player_index).name
local reporting_player_name = "<script>"
if report.reporting_player_index then
reporting_player_name = Game.get_player_by_index(report.reporting_player_index).name
end
local time = Utils.format_time(report.tick)
local time_ago = Utils.format_time(game.tick - report.tick)
local message = report.message
Gui.clear(parent)
parent.add {type="label", caption="Offender: " .. reported_player_name}
local msg_label_pane = parent.add {type="scroll-pane", vertical_scroll_policy = "auto-and-reserve-space", horizontal_scroll_policy="never"}
msg_label_pane.style.maximal_height = 400
local msg_label = msg_label_pane.add {type="label", caption="Message: " .. message}
local jail_offender_button = parent.add {type = 'button', name = jail_offender_button_name, caption = 'Jail ' .. reported_player_name}
jail_offender_button.style.height = 24
jail_offender_button.style.font = 'default-small'
jail_offender_button.style.top_padding = 0
jail_offender_button.style.bottom_padding = 0
jail_offender_button.style.left_padding = 0
jail_offender_button.style.right_padding = 0
msg_label.style.single_line = false
msg_label.style.maximal_width = 680
parent.add {type="label", caption=string.format("Time: %s (%s ago)", time, time_ago)}
parent.add {type="label", caption="Reported by: " .. reporting_player_name}
end
Module.show_reports = function(player)
local reports = global.reports or {}
local center = player.gui.center
local report_frame = center[report_frame_name]
if report_frame and report_frame.valid then
Gui.destroy(report_frame)
end
report_frame = center.add {
type = 'frame',
name = report_frame_name,
direction = 'vertical',
caption = 'User reports'
}
report_frame.style.maximal_width = 700
player.opened = report_frame
if #reports > 1 then
local scroll_pane = report_frame.add{type = "scroll-pane", horizontal_scroll_policy = "auto-and-reserve-space", vertical_scroll_policy="never"}
local tab_flow = scroll_pane.add{type="flow"}
for k,report in pairs(reports) do
local button_cell = tab_flow.add{type="flow", caption="reportuid" .. k}
button_cell.add {
type="button",
name=report_tab_button_name,
caption = Game.get_player_by_index(report.reported_player_index).name
}
end
end
local report_body = report_frame.add {type = "scroll-pane", name = report_body_name, horizontal_scroll_policy = "never", vertical_scroll_policy="never"}
report_frame.add {type = 'button', name = report_close_button_name, caption = 'Close'}
draw_report(report_body, #reports)
end
function Module.report(reporting_player, reported_player, message)
local player_index
if reporting_player then
player_index = reporting_player.index
end
table.insert(global.reports, {reporting_player_index = player_index, reported_player_index = reported_player.index, message = message, tick = game.tick})
local notified = false
for _,p in pairs(game.players) do
if p.admin and p.connected then
p.play_sound{path='utility/tutorial_notice', volume_modifier = 1}
Module.show_reports(p)
if p.afk_time < 3600 then notified = true end
end
end
if not notified then
for _,p in pairs(game.players) do
if p.admin then
Module.show_reports(p)
end
end
end
end
function Module.cmd_report(cmd)
local reporting_player = game.player
if reporting_player then
local params = {}
for param in string.gmatch(cmd.parameter, '%S+') do
table.insert(params, param)
end
if #params < 2 then
reporting_player.print('Please enter then name of the offender and the reason for the report.')
return nil
end
local reported_player_name = params[1] or ''
local reported_player = game.players[reported_player_name]
if not reported_player then
reporting_player.print(reported_player_name .. ' does not exist.')
return nil
end
Module.report(reporting_player, reported_player, string.sub(cmd.parameter, string.len(params[1]) + 2))
end
end
-- Places a target in jail as long as player is admin or server
function Module.jail(target_player, player)
-- Set the name of the jail permission group
local jail_name = 'Jail'
local print
local jailed_by
if player then
jailed_by = "a server admin"
print = player.print
else
jailed_by = "script for causing too many collapses"
print = log
end
if not target_player then
print('Unknown player.')
return
end
local permissions = game.permissions
-- Check if the permission group exists, if it doesn't, create it.
local permission_group = permissions.get_group(jail_name)
if not permission_group then
permission_group = permissions.create_group(jail_name)
end
if target_player.permission_group == permission_group then
print('Player ' .. target_player.name .. ' is already in jail.')
return
end
-- Set all permissions to disabled
for action_name, _ in pairs(defines.input_action) do
permission_group.set_allows_action(defines.input_action[action_name], false)
end
-- Enable writing to console to allow a person to speak
permission_group.set_allows_action(defines.input_action.write_to_console, true)
permission_group.set_allows_action(defines.input_action.edit_permission_group, true)
-- Kick player out of vehicle
target_player.driving=false
-- Add player to jail group
permission_group.add_player(target_player)
-- If a player is shooting when they're jailed they can't stop shooting, so we change their shooting state
if target_player.shooting_state.state ~= 0 then
target_player.shooting_state.state = {state = defines.shooting.not_shooting, position = {0,0}}
end
-- Check that it worked
if target_player.permission_group == permission_group then
-- Let admin know it worked, let target know what's going on.
print(target_player.name .. ' has been jailed. They have been advised of this.')
target_player.print(prefix)
target_player.print('You have been placed in jail by ' .. jailed_by .. '. The only action avaliable to you is chatting.')
target_player.print('Please respond to inquiries from the admins.', {r = 1, g = 1, b = 0, a = 1})
Utils.print_admins(target_player.name .. 'has been jailed by' .. player.name)
Utils.log_command(player, 'jail', target_player.name)
else
-- Let admin know it didn't work.
print('Something went wrong in the jailing of ' .. target_player.name .. '. You can still change their group via /permissions.')
end
end
function Module.unjail_player(cmd)
local default_group = 'Default'
local player = game.player
-- Check if the player can run the command
if player and not player.admin then
Utils.cant_run(cmd.name)
return
end
-- Check if the target is valid (copied from the invoke command)
local target = cmd['parameter']
if target == nil then
Game.player_print('Usage: /unjail <player>')
return
end
local target_player = game.players[target]
if not target_player then
Game.player_print('Unknown player.')
return
end
local permissions = game.permissions
-- Check if the permission group exists, if it doesn't, create it.
local permission_group = permissions.get_group(default_group)
if not permission_group then
permission_group = permissions.create_group(default_group)
end
local jail_permission_group = permissions.get_group('Jail')
if (not jail_permission_group) or target_player.permission_group ~= jail_permission_group then
Game.player_print('The player ' .. target .. ' is already not in Jail.')
return
end
-- Move player
permission_group.add_player(target)
-- Set player to a non-shooting state (solves a niche case where players jailed while shooting will be locked into a shooting state)
target_player.shooting_state.state = 0
-- Check that it worked
if target_player.permission_group == permission_group then
-- Let admin know it worked, let target know what's going on.
Game.player_print(target .. ' has been returned to the default group. They have been advised of this.')
target_player.print(prefix)
target_player.print('Your ability to perform actions has been restored', {r = 0, g = 1, b = 0, a = 1})
target_player.print(prefix_e)
else
-- Let admin know it didn't work.
Game.player_print(
'Something went wrong in the unjailing of ' ..
target .. '. You can still change their group via /permissions and inform them.'
)
end
end
Gui.on_custom_close(
report_frame_name,
function(event)
Gui.destroy(event.element)
end
)
Gui.on_click(
report_close_button_name,
function(event)
Gui.destroy(event.element.parent)
end
)
Gui.on_click(
jail_offender_button_name,
function(event)
local target_name = string.sub(event.element.caption, 6)
local target = game.players[target_name]
Module.jail(target, event.player)
end
)
Gui.on_click(
report_tab_button_name,
function(event)
local center = event.player.gui.center
local report_frame = center[report_frame_name]
local report_uid_str = string.sub(event.element.parent.caption, 10)
local report_uid = tonumber(report_uid_str)
draw_report(report_frame[report_body_name], report_uid)
end
)
local reporting_popup_name = Gui.uid_name()
local reporting_cancel_button_name = Gui.uid_name()
local reporting_submit_button_name = Gui.uid_name()
local reporting_input_name = Gui.uid_name()
Module.spawn_reporting_popup = function(player, reported_player)
local center = player.gui.center
local reporting_popup = center[reporting_popup_name]
if reporting_popup and reporting_popup.valid then
Gui.destroy(reporting_popup)
end
reporting_popup = center.add {
type = 'frame',
name = reporting_popup_name,
direction = 'vertical',
caption = 'Report player ' .. reported_player.name
}
Gui.set_data(reporting_popup, {reported_player_index = reported_player.index})
reporting_popup.style.maximal_width = 500
player.opened = reporting_popup
reporting_popup.add {
type = 'label',
caption = 'Report message:'
}
local input = reporting_popup.add {type = 'text-box', name=reporting_input_name}
input.style.width = 400
input.style.height = 85
local button_flow = reporting_popup.add {type = "flow"}
button_flow.add {type = "button", name = reporting_submit_button_name, caption="Submit"}
button_flow.add {type = "button", name = reporting_cancel_button_name, caption="Cancel"}
end
Gui.on_custom_close(
reporting_popup_name,
function(event)
Gui.destroy(event.element)
end
)
Gui.on_click(
reporting_cancel_button_name,
function(event)
local frame = event.element.parent.parent
Gui.destroy(frame)
end
)
Gui.on_click(
reporting_submit_button_name,
function(event)
local frame = event.element.parent.parent
local msg = frame[reporting_input_name].text
local data = Gui.get_data(frame)
local reported_player_index = data["reported_player_index"]
local print = event.player.print
Gui.destroy(frame)
Module.report(event.player, Game.get_player_by_index(reported_player_index), msg)
print(prefix)
print("You have successfully reported the player: " .. Game.get_player_by_index(reported_player_index).name)
print(prefix_e)
end
)
return Module

View File

@ -1,159 +1,159 @@
--[[-- info
Original (javascript) version: https://hastebin.com/udakacavap.js
Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factor
]]
-- dependencies
local Global = require 'utils.global'
local random = math.random
local round = math.round
-- this
local AlienEvolutionProgress = {}
local alien_cache = {
biters = {
evolution = -1,
cache = {},
},
spitters = {
evolution = -1,
cache = {},
},
}
Global.register({
alien_cache = alien_cache,
}, function(tbl)
alien_cache = tbl.alien_cache
end)
-- values are in the form {evolution, weight}
local biters = {
{'small-biter', {{0.0, 0.3}, {0.6, 0.0}}},
{'medium-biter', {{0.2, 0.0}, {0.6, 0.3}, {0.7, 0.1}}},
{'big-biter', {{0.5, 0.0}, {1.0, 0.4}}},
{'behemoth-biter', {{0.9, 0.0}, {1.0, 0.3}}},
}
local spitters = {
{'small-biter', {{0.0, 0.3}, {0.35, 0.0}}},
{'small-spitter', {{0.25, 0.0}, {0.5, 0.3}, {0.7, 0.0}}},
{'medium-spitter', {{0.4, 0.0}, {0.7, 0.3}, {0.9, 0.1}}},
{'big-spitter', {{0.5, 0.0}, {1.0, 0.4}}},
{'behemoth-spitter', {{0.9, 0.0}, {1.0, 0.3}}},
}
local function lerp(low, high, pos)
local s = high[1] - low[1];
local l = (pos - low[1]) / s;
return (low[2] * (1 - l)) + (high[2] * l)
end
local function get_values(map, evo)
local result = {}
local sum = 0
for _, data in pairs(map) do
local list = data[2];
local low = list[1];
local high = list[#list];
for _, val in pairs(list) do
if(val[1] <= evo and val[1] > low[1]) then
low = val;
end
if(val[1] >= evo and val[1] < high[1]) then
high = val
end
end
local val
if (evo <= low[1]) then
val = low[2]
elseif (evo >= high[1]) then
val = high[2];
else
val = lerp(low, high, evo)
end
sum = sum + val;
result[data[1]] = val;
end
for index, _ in pairs(result) do
result[index] = result[index] / sum
end
return result;
end
local function get_name_by_random(collection)
local pre_calculated = random()
local current = 0
for name, probability in pairs(collection) do
current = current + probability
if (current >= pre_calculated) then
return name
end
end
Debug.print('AlienEvolutionProgress.get_name_by_random: Current \'' .. current .. '\' should be higher or equal to random \'' .. pre_calculated .. '\'')
end
function AlienEvolutionProgress.getBiterValues(evolution)
local evolution_value = round(evolution * 100)
if (alien_cache.biters.evolution < evolution_value) then
alien_cache.biters.evolution = evolution_value
alien_cache.biters.cache = get_values(biters, evolution)
end
return alien_cache.biters.cache
end
function AlienEvolutionProgress.getSpitterValues(evolution)
local evolution_value = round(evolution * 100)
if (alien_cache.spitters.evolution < evolution_value) then
alien_cache.spitters.evolution = evolution_value
alien_cache.spitters.cache = get_values(spitters, evolution)
end
return alien_cache.spitters.cache
end
function AlienEvolutionProgress.getBitersByEvolution(total_biters, evolution)
local biters_calculated = {}
local map = AlienEvolutionProgress.getBiterValues(evolution)
for i = 1, total_biters do
local name = get_name_by_random(map)
if (nil == biters_calculated[name]) then
biters_calculated[name] = 1
else
biters_calculated[name] = biters_calculated[name] + 1
end
end
return biters_calculated
end
function AlienEvolutionProgress.getSpittersByEvolution(total_spitters, evolution)
local spitters_calculated = {}
local map = AlienEvolutionProgress.getSpitterValues(evolution)
for i = 1, total_spitters do
local name = get_name_by_random(map)
if (nil == spitters_calculated[name]) then
spitters_calculated[name] = 1
else
spitters_calculated[name] = spitters_calculated[name] + 1
end
end
return spitters_calculated
end
return AlienEvolutionProgress
--[[-- info
Original (javascript) version: https://hastebin.com/udakacavap.js
Can be tested against: https://wiki.factorio.com/Enemies#Spawn_chances_by_evolution_factor
]]
-- dependencies
local Global = require 'utils.global'
local random = math.random
local round = math.round
-- this
local AlienEvolutionProgress = {}
local alien_cache = {
biters = {
evolution = -1,
cache = {},
},
spitters = {
evolution = -1,
cache = {},
},
}
Global.register({
alien_cache = alien_cache,
}, function(tbl)
alien_cache = tbl.alien_cache
end)
-- values are in the form {evolution, weight}
local biters = {
{'small-biter', {{0.0, 0.3}, {0.6, 0.0}}},
{'medium-biter', {{0.2, 0.0}, {0.6, 0.3}, {0.7, 0.1}}},
{'big-biter', {{0.5, 0.0}, {1.0, 0.4}}},
{'behemoth-biter', {{0.9, 0.0}, {1.0, 0.3}}},
}
local spitters = {
{'small-biter', {{0.0, 0.3}, {0.35, 0.0}}},
{'small-spitter', {{0.25, 0.0}, {0.5, 0.3}, {0.7, 0.0}}},
{'medium-spitter', {{0.4, 0.0}, {0.7, 0.3}, {0.9, 0.1}}},
{'big-spitter', {{0.5, 0.0}, {1.0, 0.4}}},
{'behemoth-spitter', {{0.9, 0.0}, {1.0, 0.3}}},
}
local function lerp(low, high, pos)
local s = high[1] - low[1];
local l = (pos - low[1]) / s;
return (low[2] * (1 - l)) + (high[2] * l)
end
local function get_values(map, evo)
local result = {}
local sum = 0
for _, data in pairs(map) do
local list = data[2];
local low = list[1];
local high = list[#list];
for _, val in pairs(list) do
if(val[1] <= evo and val[1] > low[1]) then
low = val;
end
if(val[1] >= evo and val[1] < high[1]) then
high = val
end
end
local val
if (evo <= low[1]) then
val = low[2]
elseif (evo >= high[1]) then
val = high[2];
else
val = lerp(low, high, evo)
end
sum = sum + val;
result[data[1]] = val;
end
for index, _ in pairs(result) do
result[index] = result[index] / sum
end
return result;
end
local function get_name_by_random(collection)
local pre_calculated = random()
local current = 0
for name, probability in pairs(collection) do
current = current + probability
if (current >= pre_calculated) then
return name
end
end
Debug.print('AlienEvolutionProgress.get_name_by_random: Current \'' .. current .. '\' should be higher or equal to random \'' .. pre_calculated .. '\'')
end
function AlienEvolutionProgress.getBiterValues(evolution)
local evolution_value = round(evolution * 100)
if (alien_cache.biters.evolution < evolution_value) then
alien_cache.biters.evolution = evolution_value
alien_cache.biters.cache = get_values(biters, evolution)
end
return alien_cache.biters.cache
end
function AlienEvolutionProgress.getSpitterValues(evolution)
local evolution_value = round(evolution * 100)
if (alien_cache.spitters.evolution < evolution_value) then
alien_cache.spitters.evolution = evolution_value
alien_cache.spitters.cache = get_values(spitters, evolution)
end
return alien_cache.spitters.cache
end
function AlienEvolutionProgress.getBitersByEvolution(total_biters, evolution)
local biters_calculated = {}
local map = AlienEvolutionProgress.getBiterValues(evolution)
for i = 1, total_biters do
local name = get_name_by_random(map)
if (nil == biters_calculated[name]) then
biters_calculated[name] = 1
else
biters_calculated[name] = biters_calculated[name] + 1
end
end
return biters_calculated
end
function AlienEvolutionProgress.getSpittersByEvolution(total_spitters, evolution)
local spitters_calculated = {}
local map = AlienEvolutionProgress.getSpitterValues(evolution)
for i = 1, total_spitters do
local name = get_name_by_random(map)
if (nil == spitters_calculated[name]) then
spitters_calculated[name] = 1
else
spitters_calculated[name] = spitters_calculated[name] + 1
end
end
return spitters_calculated
end
return AlienEvolutionProgress

View File

@ -1,224 +1,224 @@
-- dependencies
local min = math.min
local max = math.max
local floor = math.floor
local abs = math.abs
-- this
local Debug = {}
-- private state
local debug = false
local cheats = false
function Debug.enable_debug()
debug = true
end
function Debug.disable_debug()
debug = false
end
function Debug.enable_cheats()
cheats = true
end
function Debug.disable_cheats()
cheats = true
end
global.message_count = 0
--[[--
Shows the given message if debug is enabled.
@param message string
]]
function Debug.print(message)
if type(message) ~= 'string' and type(message) ~= 'number' and type(message) ~= 'boolean' then message = type(message) end
global.message_count = global.message_count + 1
if (debug) then
game.print('[' .. global.message_count .. '] ' .. tostring(message))
log('[' .. global.message_count .. '] ' .. tostring(message))
end
end
--[[--
Shows the given message with serpent enabled, if debug is enabled.
@param message string
]]
function Debug.print_serpent(message)
Debug.print(serpent.line(message))
end
--[[--
Shows the given message if _DEBUG == true for a given position.
@param x number
@param y number
@param message string
]]
function Debug.print_position(position, message)
message = message or ''
if type(message) ~= 'string' and type(message) ~= 'number' and type(message) ~= 'boolean' then message = type(message) end
global.message_count = global.message_count + 1
if (debug) then
game.print('[' .. global.message_count .. '] {x=' .. position.x .. ', y=' .. position.y .. '} ' .. tostring(message))
end
end
--[[--
Executes the given callback if cheating is enabled.
@param callback function
]]
function Debug.cheat(callback)
if (cheats) then
callback()
end
end
--[[--
Prints a colored value on a location.
@param value between -1 and 1
@param surface LuaSurface
@param position Position {x, y}
@param scale float
@param offset float
@param immutable bool if immutable, only set, never do a surface lookup, values never change
]]
function Debug.print_grid_value(value, surface, position, scale, offset, immutable)
local is_string = type(value) == 'string'
local color = {r = 1, g = 1, b = 1}
text = value
if type(immutable) ~= 'boolean' then
immutable = false
end
if not is_string then
scale = scale or 1
offset = offset or 0
position = {x = position.x + offset, y = position.y + offset}
local r = max(1, value) / scale
local g = 1 - abs(value) / scale
local b = min(1, value) / scale
if (r > 0) then
r = 0
end
if (b < 0) then
b = 0
end
if (g < 0) then
g = 0
end
r = abs(r)
color = { r = r, g = g, b = b}
-- round at precision of 2
text = floor(100 * value) * 0.01
if (0 == text) then
text = '0.00'
end
end
if not immutable then
local text_entity = surface.find_entity('flying-text', position)
if text_entity then
text_entity.text = text
text_entity.color = color
return
end
end
surface.create_entity{
name = 'flying-text',
color = color,
text = text,
position = position
}.active = false
end
--[[--
Prints a colored value on a location. When given a color_value and a delta_color,
will change the color of the text from the base to base + value * delta. This will
make the color of the text range from 'base_color' to 'base_color + delta_color'
as the color_value ranges from 0 to 1
@param value of number to be displayed
@param surface LuaSurface
@param position Position {x, y}
@param scale float
@param offset float position offset
@param immutable bool if immutable, only set, never do a surface lookup, values never change
@param color_value float How far along the range of values of colors the value is to be displayed
@param base_color {r,g,b} The color for the text to be if color_value is 0
@param delta_color {r,g,b} The amount to correct the base_color if color_value is 1
@param under_bound {r,g,b} The color to be used if color_value < 0
@param over_bound {r,g,b} The color to be used if color_value > 1
]]
function Debug.print_colored_grid_value(value, surface, position, scale, offset, immutable,
color_value, base_color, delta_color, under_bound, over_bound)
local is_string = type(value) == 'string'
-- default values:
local color = base_color or {r = 1, g = 1, b = 1}
local d_color = delta_color or {r = 0, g = 0, b = 0}
local u_color = under_bound or color
local o_color = over_bound or color
if (color_value < 0) then
color = u_color
elseif (color_value > 1) then
color = o_color
else
color = { r = color.r + color_value * d_color.r,
g = color.g + color_value * d_color.g,
b = color.b + color_value * d_color.b }
end
text = value
if type(immutable) ~= 'boolean' then
immutable = false
end
if not is_string then
offset = offset or 0
position = {x = position.x + offset, y = position.y + offset}
-- round at precision of 2
text = floor(100 * value) * 0.01
if (0 == text) then
text = '0.00'
end
end
if not immutable then
local text_entity = surface.find_entity('flying-text', position)
if text_entity then
text_entity.text = text
text_entity.color = color
return
end
end
surface.create_entity{
name = 'flying-text',
color = color,
text = text,
position = position
}.active = false
end
return Debug
-- dependencies
local min = math.min
local max = math.max
local floor = math.floor
local abs = math.abs
-- this
local Debug = {}
-- private state
local debug = false
local cheats = false
function Debug.enable_debug()
debug = true
end
function Debug.disable_debug()
debug = false
end
function Debug.enable_cheats()
cheats = true
end
function Debug.disable_cheats()
cheats = true
end
global.message_count = 0
--[[--
Shows the given message if debug is enabled.
@param message string
]]
function Debug.print(message)
if type(message) ~= 'string' and type(message) ~= 'number' and type(message) ~= 'boolean' then message = type(message) end
global.message_count = global.message_count + 1
if (debug) then
game.print('[' .. global.message_count .. '] ' .. tostring(message))
log('[' .. global.message_count .. '] ' .. tostring(message))
end
end
--[[--
Shows the given message with serpent enabled, if debug is enabled.
@param message string
]]
function Debug.print_serpent(message)
Debug.print(serpent.line(message))
end
--[[--
Shows the given message if _DEBUG == true for a given position.
@param x number
@param y number
@param message string
]]
function Debug.print_position(position, message)
message = message or ''
if type(message) ~= 'string' and type(message) ~= 'number' and type(message) ~= 'boolean' then message = type(message) end
global.message_count = global.message_count + 1
if (debug) then
game.print('[' .. global.message_count .. '] {x=' .. position.x .. ', y=' .. position.y .. '} ' .. tostring(message))
end
end
--[[--
Executes the given callback if cheating is enabled.
@param callback function
]]
function Debug.cheat(callback)
if (cheats) then
callback()
end
end
--[[--
Prints a colored value on a location.
@param value between -1 and 1
@param surface LuaSurface
@param position Position {x, y}
@param scale float
@param offset float
@param immutable bool if immutable, only set, never do a surface lookup, values never change
]]
function Debug.print_grid_value(value, surface, position, scale, offset, immutable)
local is_string = type(value) == 'string'
local color = {r = 1, g = 1, b = 1}
text = value
if type(immutable) ~= 'boolean' then
immutable = false
end
if not is_string then
scale = scale or 1
offset = offset or 0
position = {x = position.x + offset, y = position.y + offset}
local r = max(1, value) / scale
local g = 1 - abs(value) / scale
local b = min(1, value) / scale
if (r > 0) then
r = 0
end
if (b < 0) then
b = 0
end
if (g < 0) then
g = 0
end
r = abs(r)
color = { r = r, g = g, b = b}
-- round at precision of 2
text = floor(100 * value) * 0.01
if (0 == text) then
text = '0.00'
end
end
if not immutable then
local text_entity = surface.find_entity('flying-text', position)
if text_entity then
text_entity.text = text
text_entity.color = color
return
end
end
surface.create_entity{
name = 'flying-text',
color = color,
text = text,
position = position
}.active = false
end
--[[--
Prints a colored value on a location. When given a color_value and a delta_color,
will change the color of the text from the base to base + value * delta. This will
make the color of the text range from 'base_color' to 'base_color + delta_color'
as the color_value ranges from 0 to 1
@param value of number to be displayed
@param surface LuaSurface
@param position Position {x, y}
@param scale float
@param offset float position offset
@param immutable bool if immutable, only set, never do a surface lookup, values never change
@param color_value float How far along the range of values of colors the value is to be displayed
@param base_color {r,g,b} The color for the text to be if color_value is 0
@param delta_color {r,g,b} The amount to correct the base_color if color_value is 1
@param under_bound {r,g,b} The color to be used if color_value < 0
@param over_bound {r,g,b} The color to be used if color_value > 1
]]
function Debug.print_colored_grid_value(value, surface, position, scale, offset, immutable,
color_value, base_color, delta_color, under_bound, over_bound)
local is_string = type(value) == 'string'
-- default values:
local color = base_color or {r = 1, g = 1, b = 1}
local d_color = delta_color or {r = 0, g = 0, b = 0}
local u_color = under_bound or color
local o_color = over_bound or color
if (color_value < 0) then
color = u_color
elseif (color_value > 1) then
color = o_color
else
color = { r = color.r + color_value * d_color.r,
g = color.g + color_value * d_color.g,
b = color.b + color_value * d_color.b }
end
text = value
if type(immutable) ~= 'boolean' then
immutable = false
end
if not is_string then
offset = offset or 0
position = {x = position.x + offset, y = position.y + offset}
-- round at precision of 2
text = floor(100 * value) * 0.01
if (0 == text) then
text = '0.00'
end
end
if not immutable then
local text_entity = surface.find_entity('flying-text', position)
if text_entity then
text_entity.text = text
text_entity.color = color
return
end
end
surface.create_entity{
name = 'flying-text',
color = color,
text = text,
position = position
}.active = false
end
return Debug

View File

@ -1,66 +1,66 @@
--[[-- info
Provides the ability to spawn aliens.
]]
-- dependencies
local Event = require 'utils.event'
local AlienEvolutionProgress = require 'map_gen.Diggy.AlienEvolutionProgress'
local Debug = require 'map_gen.Diggy.Debug'
local Template = require 'map_gen.Diggy.Template'
local insert = table.insert
local random = math.random
-- this
local AlienSpawner = {}
local function spawn_alien(surface, x, y)
local enemy_force = game.forces.enemy
local enemy_force_evolution = enemy_force.evolution_factor
local position = {x = x, y = y}
local biters = AlienEvolutionProgress.getBitersByEvolution(random(1, 2), enemy_force_evolution)
local spitters = AlienEvolutionProgress.getSpittersByEvolution(random(1, 2), enemy_force_evolution)
local units = {}
for name, amount in pairs(biters) do
insert(units, {name = name, position = position, force = enemy_force, amount = amount})
end
for name, amount in pairs(spitters) do
insert(units, {name = name, position = position, force = enemy_force, amount = amount})
end
Template.units(surface, units, 1.5, 'small-biter')
end
--[[--
Registers all event handlers.
]]
function AlienSpawner.register(config)
local alien_minimum_distance_square = config.alien_minimum_distance ^ 2
Event.add(Template.events.on_void_removed, function (event)
game.forces.enemy.evolution_factor = game.forces.enemy.evolution_factor + 0.0000012
local position = event.position
local x = position.x
local y = position.y
if (x * x + y * y < alien_minimum_distance_square or config.alien_probability < random()) then
return
end
spawn_alien(event.surface, x, y)
end)
end
function AlienSpawner.get_extra_map_info(config)
return [[Alien Spawner, aliens might spawn when mining!
Spawn chance: ]] .. (config.alien_probability * 100) .. [[%
Minimum spawn distance: ]] .. config.alien_minimum_distance .. ' tiles'
end
function AlienSpawner.on_init()
-- base factorio = pollution_factor = 0.000015
game.map_settings.enemy_evolution.pollution_factor = 0.000004
end
return AlienSpawner
--[[-- info
Provides the ability to spawn aliens.
]]
-- dependencies
local Event = require 'utils.event'
local AlienEvolutionProgress = require 'map_gen.Diggy.AlienEvolutionProgress'
local Debug = require 'map_gen.Diggy.Debug'
local Template = require 'map_gen.Diggy.Template'
local insert = table.insert
local random = math.random
-- this
local AlienSpawner = {}
local function spawn_alien(surface, x, y)
local enemy_force = game.forces.enemy
local enemy_force_evolution = enemy_force.evolution_factor
local position = {x = x, y = y}
local biters = AlienEvolutionProgress.getBitersByEvolution(random(1, 2), enemy_force_evolution)
local spitters = AlienEvolutionProgress.getSpittersByEvolution(random(1, 2), enemy_force_evolution)
local units = {}
for name, amount in pairs(biters) do
insert(units, {name = name, position = position, force = enemy_force, amount = amount})
end
for name, amount in pairs(spitters) do
insert(units, {name = name, position = position, force = enemy_force, amount = amount})
end
Template.units(surface, units, 1.5, 'small-biter')
end
--[[--
Registers all event handlers.
]]
function AlienSpawner.register(config)
local alien_minimum_distance_square = config.alien_minimum_distance ^ 2
Event.add(Template.events.on_void_removed, function (event)
game.forces.enemy.evolution_factor = game.forces.enemy.evolution_factor + 0.0000012
local position = event.position
local x = position.x
local y = position.y
if (x * x + y * y < alien_minimum_distance_square or config.alien_probability < random()) then
return
end
spawn_alien(event.surface, x, y)
end)
end
function AlienSpawner.get_extra_map_info(config)
return [[Alien Spawner, aliens might spawn when mining!
Spawn chance: ]] .. (config.alien_probability * 100) .. [[%
Minimum spawn distance: ]] .. config.alien_minimum_distance .. ' tiles'
end
function AlienSpawner.on_init()
-- base factorio = pollution_factor = 0.000015
game.map_settings.enemy_evolution.pollution_factor = 0.000004
end
return AlienSpawner

View File

@ -1,57 +1,57 @@
--[[-- info
Provides the ability to setup a player when first joined.
]]
-- dependencies
local Event = require 'utils.event'
local Global = require 'utils.global'
local CaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
local Game = require 'utils.game'
local Report = require 'features.report'
-- this
local Antigrief = {}
global.Antigrief = {
autojail = false,
jailed_players = {},
last_collapse = 0
}
local allowed_collapses_first_hour = 0
local player_collapses = {}
Global.register({
cave_collapse_disabled = cave_collapse_disabled
}, function(tbl)
cave_collapse_disabled = tbl.cave_collapse_disabled
end)
--[[--
Registers all event handlers.
]]
function Antigrief.register(config)
global.Antigrief.autojail = config.autojail
allowed_collapses_first_hour = config.allowed_collapses_first_hour
end
Event.add(CaveCollapse.events.on_collapse, function(event)
local player_index = event.player_index
if player_index and global.Antigrief.last_collapse ~= game.tick then
global.Antigrief.last_collapse = game.tick
local count = player_collapses[player_index] or 0
count = count + 1
player_collapses[player_index] = count
local player = Game.get_player_by_index(player_index)
if global.Antigrief.autojail and count > allowed_collapses_first_hour and player.online_time < 216000 and not global.Antigrief.jailed_players[player_index] then
Report.jail(player)
Report.report(nil, player, string.format("Caused %d collapses in the first hour", count))
global.Antigrief.jailed_players[player_index] = true
end
end
end)
return Antigrief
--[[-- info
Provides the ability to setup a player when first joined.
]]
-- dependencies
local Event = require 'utils.event'
local Global = require 'utils.global'
local CaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
local Game = require 'utils.game'
local Report = require 'features.report'
-- this
local Antigrief = {}
global.Antigrief = {
autojail = false,
jailed_players = {},
last_collapse = 0
}
local allowed_collapses_first_hour = 0
local player_collapses = {}
Global.register({
cave_collapse_disabled = cave_collapse_disabled
}, function(tbl)
cave_collapse_disabled = tbl.cave_collapse_disabled
end)
--[[--
Registers all event handlers.
]]
function Antigrief.register(config)
global.Antigrief.autojail = config.autojail
allowed_collapses_first_hour = config.allowed_collapses_first_hour
end
Event.add(CaveCollapse.events.on_collapse, function(event)
local player_index = event.player_index
if player_index and global.Antigrief.last_collapse ~= game.tick then
global.Antigrief.last_collapse = game.tick
local count = player_collapses[player_index] or 0
count = count + 1
player_collapses[player_index] = count
local player = Game.get_player_by_index(player_index)
if global.Antigrief.autojail and count > allowed_collapses_first_hour and player.online_time < 216000 and not global.Antigrief.jailed_players[player_index] then
Report.jail(player)
Report.report(nil, player, string.format("Caused %d collapses in the first hour", count))
global.Antigrief.jailed_players[player_index] = true
end
end
end)
return Antigrief

View File

@ -1,242 +1,242 @@
--[[-- info
Provides the ability to collect coins and send them to space.
]]
-- dependencies
local Event = require 'utils.event'
local Game = require 'utils.game'
local ScoreTable = require 'map_gen.Diggy.ScoreTable'
local Debug = require 'map_gen.Diggy.Debug'
local Template = require 'map_gen.Diggy.Template'
local Perlin = require 'map_gen.shared.perlin_noise'
local random = math.random
local ceil = math.ceil
local Gui = require 'utils.gui'
local utils = require 'utils.utils'
-- this
local ArtefactHunting = {}
-- some GUI stuff
local function redraw_table(data)
local list = data.list
Gui.clear(list)
data.frame.caption = 'Scoretable'
local score_keys = ScoreTable.all_keys()
for _, data in pairs(score_keys) do
local val = ScoreTable.get(data)
local table = list.add({type = 'table', column_count = 2})
local key = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Key', caption = data})
key.style.minimal_width = 175
local val = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Val', caption = utils.comma_value(val)})
val.style.minimal_width = 225
end
end
local function toggle(event)
local player = event.player
local center = player.gui.left
local frame = center['Diggy.ArtefactHunting.Frame']
if (frame and event.trigger == nil) then
Gui.destroy(frame)
return
elseif (frame) then
local data = Gui.get_data(frame)
redraw_table(data)
return
end
frame = center.add({name = 'Diggy.ArtefactHunting.Frame', type = 'frame', direction = 'vertical'})
local scroll_pane = frame.add({type = 'scroll-pane'})
scroll_pane.style.maximal_height = 400
frame.add({ type = 'button', name = 'Diggy.ArtefactHunting.Button', caption = 'Close'})
local data = {
frame = frame,
list = scroll_pane
}
redraw_table(data)
Gui.set_data(frame, data)
end
local function on_player_created(event)
Game.get_player_by_index(event.player_index).gui.top.add({
name = 'Diggy.ArtefactHunting.Button',
type = 'sprite-button',
sprite = 'item/steel-axe',
})
end
Gui.on_click('Diggy.ArtefactHunting.Button', toggle)
Gui.on_custom_close('Diggy.ArtefactHunting.Frame', function (event)
event.element.destroy()
end)
function ArtefactHunting.update_gui()
for _, p in ipairs(game.connected_players) do
local frame = p.gui.left['Diggy.ArtefactHunting.Frame']
if frame and frame.valid then
local data = {player = p, trigger = 'update_gui'}
toggle(data)
end
end
end
--[[--
Registers all event handlers.
]]
function ArtefactHunting.register(config)
Event.add(defines.events.on_player_created, on_player_created)
Event.on_nth_tick(61, ArtefactHunting.update_gui)
ScoreTable.reset('Coins sent to space')
local seed
local function get_noise(surface, x, y)
seed = seed or surface.map_gen_settings.seed + surface.index + 300
return Perlin.noise(x * config.noise_variance * 0.9, y * config.noise_variance * 1.1, seed)
end
local distance_required = config.minimal_treasure_chest_distance * config.minimal_treasure_chest_distance
Event.add(defines.events.on_rocket_launched, function (event)
local coins = event.rocket.get_inventory(defines.inventory.rocket).get_item_count('coin')
if coins > 0 then
local sum = ScoreTable.add('Coins sent to space', coins)
game.print('sent ' .. coins .. ' coins into space! The space station is now holding ' .. sum .. ' coins.')
end
end)
Event.add(Template.events.on_void_removed, function (event)
local position = event.position
local x = position.x
local y = position.y
if (x * x + y * y <= distance_required) then
return
end
local surface = event.surface
if get_noise(surface, x, y) < config.treasure_chest_noise_threshold then
return
end
local chest = surface.create_entity({name = 'steel-chest', position = position, force = game.forces.player})
if not chest then
return
end
for name, prototype in pairs(config.treasure_chest_raffle) do
if random() <= prototype.chance then
chest.insert({name = name, count = random(prototype.min, prototype.max)})
end
end
end)
local modifiers = config.alien_coin_modifiers
local function picked_up_coins(player_index, count)
local text
if count == 1 then
text = '+1 coin'
ScoreTable.increment('Collected coins')
else
text = '+' .. count ..' coins'
ScoreTable.add('Collected coins', count)
end
Game.print_player_floating_text(player_index, text, {r = 255, g = 215, b = 0})
end
ScoreTable.reset('Collected coins')
Event.add(defines.events.on_entity_died, function (event)
local entity = event.entity
local force = entity.force
if force.name ~= 'enemy' then
return
end
local cause = event.cause
if not cause or cause.type ~= 'player' or not cause.valid then
return
end
local modifier = modifiers[entity.name] or 1
local evolution_multiplier = force.evolution_factor * 11
local count = random(
ceil(2 * evolution_multiplier * 0.1),
ceil(5 * (evolution_multiplier * evolution_multiplier + modifier) * 0.1)
)
entity.surface.create_entity({
name = 'item-on-ground',
position = entity.position,
stack = {name = 'coin', count = count}
})
end)
Event.add(defines.events.on_picked_up_item, function (event)
local stack = event.item_stack
if stack.name ~= 'coin' then
return
end
picked_up_coins(event.player_index, stack.count)
end)
Event.add(defines.events.on_pre_player_mined_item, function (event)
if event.entity.type ~= 'simple-entity' then
return
end
if random() > config.mining_artefact_chance then
return
end
local count = random(config.mining_artefact_amount.min, config.mining_artefact_amount.max)
local player_index = event.player_index
Game.get_player_by_index(player_index).insert({name = 'coin', count = count})
picked_up_coins(player_index, count)
end)
if (config.display_chest_locations) then
Event.add(defines.events.on_chunk_generated, function (event)
local surface = event.surface
local area = event.area
for x = area.left_top.x, area.left_top.x + 31 do
local sq_x = x * x
for y = area.left_top.y, area.left_top.y + 31 do
if sq_x + y * y >= distance_required and get_noise(surface, x, y) >= config.treasure_chest_noise_threshold then
Debug.print_grid_value('chest', surface, {x = x, y = y}, nil, nil, true)
end
end
end
end)
end
end
function ArtefactHunting.get_extra_map_info(config)
return 'Artefact Hunting, find precious coins while mining and launch them to the surface!'
end
return ArtefactHunting
--[[-- info
Provides the ability to collect coins and send them to space.
]]
-- dependencies
local Event = require 'utils.event'
local Game = require 'utils.game'
local ScoreTable = require 'map_gen.Diggy.ScoreTable'
local Debug = require 'map_gen.Diggy.Debug'
local Template = require 'map_gen.Diggy.Template'
local Perlin = require 'map_gen.shared.perlin_noise'
local random = math.random
local ceil = math.ceil
local Gui = require 'utils.gui'
local utils = require 'utils.utils'
-- this
local ArtefactHunting = {}
-- some GUI stuff
local function redraw_table(data)
local list = data.list
Gui.clear(list)
data.frame.caption = 'Scoretable'
local score_keys = ScoreTable.all_keys()
for _, data in pairs(score_keys) do
local val = ScoreTable.get(data)
local table = list.add({type = 'table', column_count = 2})
local key = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Key', caption = data})
key.style.minimal_width = 175
local val = table.add({type = 'label', name = 'Diggy.ArtefactHunting.Frame.List.Val', caption = utils.comma_value(val)})
val.style.minimal_width = 225
end
end
local function toggle(event)
local player = event.player
local center = player.gui.left
local frame = center['Diggy.ArtefactHunting.Frame']
if (frame and event.trigger == nil) then
Gui.destroy(frame)
return
elseif (frame) then
local data = Gui.get_data(frame)
redraw_table(data)
return
end
frame = center.add({name = 'Diggy.ArtefactHunting.Frame', type = 'frame', direction = 'vertical'})
local scroll_pane = frame.add({type = 'scroll-pane'})
scroll_pane.style.maximal_height = 400
frame.add({ type = 'button', name = 'Diggy.ArtefactHunting.Button', caption = 'Close'})
local data = {
frame = frame,
list = scroll_pane
}
redraw_table(data)
Gui.set_data(frame, data)
end
local function on_player_created(event)
Game.get_player_by_index(event.player_index).gui.top.add({
name = 'Diggy.ArtefactHunting.Button',
type = 'sprite-button',
sprite = 'item/steel-axe',
})
end
Gui.on_click('Diggy.ArtefactHunting.Button', toggle)
Gui.on_custom_close('Diggy.ArtefactHunting.Frame', function (event)
event.element.destroy()
end)
function ArtefactHunting.update_gui()
for _, p in ipairs(game.connected_players) do
local frame = p.gui.left['Diggy.ArtefactHunting.Frame']
if frame and frame.valid then
local data = {player = p, trigger = 'update_gui'}
toggle(data)
end
end
end
--[[--
Registers all event handlers.
]]
function ArtefactHunting.register(config)
Event.add(defines.events.on_player_created, on_player_created)
Event.on_nth_tick(61, ArtefactHunting.update_gui)
ScoreTable.reset('Coins sent to space')
local seed
local function get_noise(surface, x, y)
seed = seed or surface.map_gen_settings.seed + surface.index + 300
return Perlin.noise(x * config.noise_variance * 0.9, y * config.noise_variance * 1.1, seed)
end
local distance_required = config.minimal_treasure_chest_distance * config.minimal_treasure_chest_distance
Event.add(defines.events.on_rocket_launched, function (event)
local coins = event.rocket.get_inventory(defines.inventory.rocket).get_item_count('coin')
if coins > 0 then
local sum = ScoreTable.add('Coins sent to space', coins)
game.print('sent ' .. coins .. ' coins into space! The space station is now holding ' .. sum .. ' coins.')
end
end)
Event.add(Template.events.on_void_removed, function (event)
local position = event.position
local x = position.x
local y = position.y
if (x * x + y * y <= distance_required) then
return
end
local surface = event.surface
if get_noise(surface, x, y) < config.treasure_chest_noise_threshold then
return
end
local chest = surface.create_entity({name = 'steel-chest', position = position, force = game.forces.player})
if not chest then
return
end
for name, prototype in pairs(config.treasure_chest_raffle) do
if random() <= prototype.chance then
chest.insert({name = name, count = random(prototype.min, prototype.max)})
end
end
end)
local modifiers = config.alien_coin_modifiers
local function picked_up_coins(player_index, count)
local text
if count == 1 then
text = '+1 coin'
ScoreTable.increment('Collected coins')
else
text = '+' .. count ..' coins'
ScoreTable.add('Collected coins', count)
end
Game.print_player_floating_text(player_index, text, {r = 255, g = 215, b = 0})
end
ScoreTable.reset('Collected coins')
Event.add(defines.events.on_entity_died, function (event)
local entity = event.entity
local force = entity.force
if force.name ~= 'enemy' then
return
end
local cause = event.cause
if not cause or cause.type ~= 'player' or not cause.valid then
return
end
local modifier = modifiers[entity.name] or 1
local evolution_multiplier = force.evolution_factor * 11
local count = random(
ceil(2 * evolution_multiplier * 0.1),
ceil(5 * (evolution_multiplier * evolution_multiplier + modifier) * 0.1)
)
entity.surface.create_entity({
name = 'item-on-ground',
position = entity.position,
stack = {name = 'coin', count = count}
})
end)
Event.add(defines.events.on_picked_up_item, function (event)
local stack = event.item_stack
if stack.name ~= 'coin' then
return
end
picked_up_coins(event.player_index, stack.count)
end)
Event.add(defines.events.on_pre_player_mined_item, function (event)
if event.entity.type ~= 'simple-entity' then
return
end
if random() > config.mining_artefact_chance then
return
end
local count = random(config.mining_artefact_amount.min, config.mining_artefact_amount.max)
local player_index = event.player_index
Game.get_player_by_index(player_index).insert({name = 'coin', count = count})
picked_up_coins(player_index, count)
end)
if (config.display_chest_locations) then
Event.add(defines.events.on_chunk_generated, function (event)
local surface = event.surface
local area = event.area
for x = area.left_top.x, area.left_top.x + 31 do
local sq_x = x * x
for y = area.left_top.y, area.left_top.y + 31 do
if sq_x + y * y >= distance_required and get_noise(surface, x, y) >= config.treasure_chest_noise_threshold then
Debug.print_grid_value('chest', surface, {x = x, y = y}, nil, nil, true)
end
end
end
end)
end
end
function ArtefactHunting.get_extra_map_info(config)
return 'Artefact Hunting, find precious coins while mining and launch them to the surface!'
end
return ArtefactHunting

File diff suppressed because it is too large Load Diff

View File

@ -1,307 +1,307 @@
--[[-- info
Provides the ability to "mine" through out-of-map tiles by destroying or
mining rocks next to it.
]]
-- dependencies
local Event = require 'utils.event'
local Global = require 'utils.global'
local Game = require 'utils.game'
local Scanner = require 'map_gen.Diggy.Scanner'
local Template = require 'map_gen.Diggy.Template'
local ScoreTable = require 'map_gen.Diggy.ScoreTable'
local Debug = require 'map_gen.Diggy.Debug'
local insert = table.insert
local random = math.random
-- todo remove this dependency
local ResourceConfig = require 'map_gen.Diggy.Config'.features.ScatteredResources
local Perlin = require 'map_gen.shared.perlin_noise'
local Simplex = require 'map_gen.shared.simplex_noise'
-- this
local DiggyHole = {}
-- keeps track of the amount of times per player when they mined with a full inventory in a row
local full_inventory_mining_cache = {}
Global.register({
full_inventory_mining_cache = full_inventory_mining_cache,
}, function (tbl)
full_inventory_mining_cache = tbl.full_inventory_mining_cache
end)
local function reset_player_full_inventory_cache(player)
if not full_inventory_mining_cache[player.index] then
return
end
full_inventory_mining_cache[player.index] = nil
end
local full_inventory_message = 'Miner, you have a full inventory!\n\nMake sure to empty it before you continue digging.'
local function trigger_inventory_warning(player)
local player_index = player.index
local count = full_inventory_mining_cache[player_index]
if not count then
full_inventory_mining_cache[player_index] = 1
player.print('## - ' .. full_inventory_message, {r = 1, g = 1, b = 0, a = 1})
player.play_sound{path='utility/new_objective', volume_modifier = 1 }
return
end
full_inventory_mining_cache[player_index] = count + 1
if count % 5 == 0 then
require 'features.gui.popup'.player(player, full_inventory_message)
end
end
--[[--
Triggers a diggy diggy hole for a given sand-rock-big or rock-huge.
Will return true even if the tile behind it is immune.
@param entity LuaEntity
]]
local function diggy_hole(entity)
if ((entity.name ~= 'sand-rock-big') and (entity.name ~= 'rock-huge')) then
return
end
local tiles = {}
local rocks = {}
local surface = entity.surface
local position = entity.position
local x = position.x
local y = position.y
local out_of_map_found = Scanner.scan_around_position(surface, position, 'out-of-map');
local distance = ResourceConfig.distance(x, y)
-- source of noise for resource generation
-- index determines offset
-- '-1' is reserved for cluster mode
-- compound clusters use as many indexes as needed > 1
local base_seed
local function seeded_noise(surface, x, y, index, sources)
base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
local noise = 0
for _, settings in ipairs(sources) do
settings.type = settings.type or 'perlin'
settings.offset = settings.offset or 0
if settings.type == 'zero' then
noise = noise + 0
elseif settings.type == 'one' then
noise = noise + settings.weight * 1
elseif settings.type == 'perlin' then
noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
elseif settings.type == 'simplex' then
noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
else
Debug.print('noise type \'' .. settings.type .. '\' not recognized')
end
end
return noise
end
-- global config values
local resource_richness_weights = ResourceConfig.resource_richness_weights
local resource_richness_weights_sum = 0
for _, weight in pairs(resource_richness_weights) do
resource_richness_weights_sum = resource_richness_weights_sum + weight
end
local s_resource_weights = ResourceConfig.scattered_resource_weights
local s_resource_weights_sum = 0
for _, weight in pairs(s_resource_weights) do
s_resource_weights_sum = s_resource_weights_sum + weight
end
-- compound cluster spawning
local c_mode = ResourceConfig.cluster_mode
-- local c_clusters = Config.features.ScatteredResources.clusters
local c_clusters = require(ResourceConfig.cluster_file_location)
if ('table' ~= type(c_clusters)) then
error('cluster_file_location invalid')
end
local c_count = 0
for _, cluster in ipairs(c_clusters) do
c_count = c_count + 1
cluster.weights_sum = 0
for _, weight in pairs(cluster.weights) do
cluster.weights_sum = cluster.weights_sum + weight
end
end
local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
for name, weight in pairs(cluster.weights) do
if name == 'skip' then return false end
end
return true
end
local huge_rock_inserted = false
for _, position in pairs(out_of_map_found) do
insert(tiles, {name = 'dirt-' .. random(1, 7), position = position})
-- if (random() > 0.50) then
-- insert(rocks, {name = 'rock-huge', position = position})
if c_mode then
for index,cluster in ipairs(c_clusters) do
if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
if cluster.noise_settings.type == "connected_tendril" then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
insert(rocks, {name = 'rock-huge', position = position})
huge_rock_inserted = true
end
end
elseif cluster.noise_settings.type == "fragmented_tendril" then
local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold
and -1 * cluster.noise_settings.discriminator_threshold < noise2
and noise2 < cluster.noise_settings.discriminator_threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
insert(rocks, {name = 'rock-huge', position = position})
huge_rock_inserted = true
end
end
else
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if noise >= cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
insert(rocks, {name = 'rock-huge', position = position})
huge_rock_inserted = true
end
end
end
end
end
end
if (huge_rock_inserted == false) then
insert(rocks, {name = 'sand-rock-big', position = position})
end
end
Template.insert(surface, tiles, rocks)
end
local artificial_tiles = {
['stone-brick'] = true,
['stone-path'] = true,
['concrete'] = true,
['hazard-concrete-left'] = true,
['hazard-concrete-right'] = true,
['refined-concrete'] = true,
['refined-hazard-concrete-left'] = true,
['refined-hazard-concrete-right'] = true,
}
local function on_mined_tile(surface, tiles)
local new_tiles = {}
for _, tile in pairs(tiles) do
if (artificial_tiles[tile.old_tile.name]) then
insert(new_tiles, { name = 'dirt-' .. random(1, 7), position = tile.position})
end
end
Template.insert(surface, new_tiles, {})
end
--[[--
Registers all event handlers.
]]
function DiggyHole.register(config)
ScoreTable.reset('Void removed')
Event.add(defines.events.on_entity_died, function (event)
diggy_hole(event.entity)
end)
local enable_digging_warning = config.enable_digging_warning
Event.add(defines.events.on_player_mined_entity, function (event)
local entity = event.entity
local name = entity.name
if name == 'sand-rock-big' or name == 'rock-huge' then
event.buffer.remove({name = 'coal', count = 100})
-- this logic can be replaced once we've fully replaced the stone to surface functionality
if enable_digging_warning then
local player = Game.get_player_by_index(event.player_index)
if player and player.valid then
if player.get_main_inventory().can_insert({name = 'stone'}) then
reset_player_full_inventory_cache(player)
else
trigger_inventory_warning(player)
end
end
end
end
diggy_hole(entity)
end)
Event.add(defines.events.on_robot_mined_tile, function (event)
on_mined_tile(event.robot.surface, event.tiles)
end)
Event.add(defines.events.on_player_mined_tile, function (event)
on_mined_tile(game.surfaces[event.surface_index], event.tiles)
end)
Event.add(Template.events.on_void_removed, function ()
ScoreTable.increment('Void removed')
end)
if config.enable_debug_commands then
commands.add_command('clear-void', '<left top x> <left top y> <width> <height> <surface index> triggers Template.insert for the given area.', function(cmd)
local params = {}
local args = cmd.parameter or ''
for param in string.gmatch(args, '%S+') do
table.insert(params, param)
end
if (#params ~= 5) then
game.player.print('/clear-void requires exactly 5 arguments: <left top x> <left top y> <width> <height> <surface index>')
return
end
local left_top_x = tonumber(params[1])
local left_top_y = tonumber(params[2])
local width = tonumber(params[3])
local height = tonumber(params[4])
local surface_index = params[5]
local tiles = {}
local entities = {}
for x = 0, width do
for y = 0, height do
insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x + left_top_x, y = y + left_top_y}})
end
end
Template.insert(game.surfaces[surface_index], tiles, entities)
end
)
end
end
function DiggyHole.on_init()
game.forces.player.technologies['landfill'].enabled = false
end
return DiggyHole
--[[-- info
Provides the ability to "mine" through out-of-map tiles by destroying or
mining rocks next to it.
]]
-- dependencies
local Event = require 'utils.event'
local Global = require 'utils.global'
local Game = require 'utils.game'
local Scanner = require 'map_gen.Diggy.Scanner'
local Template = require 'map_gen.Diggy.Template'
local ScoreTable = require 'map_gen.Diggy.ScoreTable'
local Debug = require 'map_gen.Diggy.Debug'
local insert = table.insert
local random = math.random
-- todo remove this dependency
local ResourceConfig = require 'map_gen.Diggy.Config'.features.ScatteredResources
local Perlin = require 'map_gen.shared.perlin_noise'
local Simplex = require 'map_gen.shared.simplex_noise'
-- this
local DiggyHole = {}
-- keeps track of the amount of times per player when they mined with a full inventory in a row
local full_inventory_mining_cache = {}
Global.register({
full_inventory_mining_cache = full_inventory_mining_cache,
}, function (tbl)
full_inventory_mining_cache = tbl.full_inventory_mining_cache
end)
local function reset_player_full_inventory_cache(player)
if not full_inventory_mining_cache[player.index] then
return
end
full_inventory_mining_cache[player.index] = nil
end
local full_inventory_message = 'Miner, you have a full inventory!\n\nMake sure to empty it before you continue digging.'
local function trigger_inventory_warning(player)
local player_index = player.index
local count = full_inventory_mining_cache[player_index]
if not count then
full_inventory_mining_cache[player_index] = 1
player.print('## - ' .. full_inventory_message, {r = 1, g = 1, b = 0, a = 1})
player.play_sound{path='utility/new_objective', volume_modifier = 1 }
return
end
full_inventory_mining_cache[player_index] = count + 1
if count % 5 == 0 then
require 'features.gui.popup'.player(player, full_inventory_message)
end
end
--[[--
Triggers a diggy diggy hole for a given sand-rock-big or rock-huge.
Will return true even if the tile behind it is immune.
@param entity LuaEntity
]]
local function diggy_hole(entity)
if ((entity.name ~= 'sand-rock-big') and (entity.name ~= 'rock-huge')) then
return
end
local tiles = {}
local rocks = {}
local surface = entity.surface
local position = entity.position
local x = position.x
local y = position.y
local out_of_map_found = Scanner.scan_around_position(surface, position, 'out-of-map');
local distance = ResourceConfig.distance(x, y)
-- source of noise for resource generation
-- index determines offset
-- '-1' is reserved for cluster mode
-- compound clusters use as many indexes as needed > 1
local base_seed
local function seeded_noise(surface, x, y, index, sources)
base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
local noise = 0
for _, settings in ipairs(sources) do
settings.type = settings.type or 'perlin'
settings.offset = settings.offset or 0
if settings.type == 'zero' then
noise = noise + 0
elseif settings.type == 'one' then
noise = noise + settings.weight * 1
elseif settings.type == 'perlin' then
noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
elseif settings.type == 'simplex' then
noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
else
Debug.print('noise type \'' .. settings.type .. '\' not recognized')
end
end
return noise
end
-- global config values
local resource_richness_weights = ResourceConfig.resource_richness_weights
local resource_richness_weights_sum = 0
for _, weight in pairs(resource_richness_weights) do
resource_richness_weights_sum = resource_richness_weights_sum + weight
end
local s_resource_weights = ResourceConfig.scattered_resource_weights
local s_resource_weights_sum = 0
for _, weight in pairs(s_resource_weights) do
s_resource_weights_sum = s_resource_weights_sum + weight
end
-- compound cluster spawning
local c_mode = ResourceConfig.cluster_mode
-- local c_clusters = Config.features.ScatteredResources.clusters
local c_clusters = require(ResourceConfig.cluster_file_location)
if ('table' ~= type(c_clusters)) then
error('cluster_file_location invalid')
end
local c_count = 0
for _, cluster in ipairs(c_clusters) do
c_count = c_count + 1
cluster.weights_sum = 0
for _, weight in pairs(cluster.weights) do
cluster.weights_sum = cluster.weights_sum + weight
end
end
local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
for name, weight in pairs(cluster.weights) do
if name == 'skip' then return false end
end
return true
end
local huge_rock_inserted = false
for _, position in pairs(out_of_map_found) do
insert(tiles, {name = 'dirt-' .. random(1, 7), position = position})
-- if (random() > 0.50) then
-- insert(rocks, {name = 'rock-huge', position = position})
if c_mode then
for index,cluster in ipairs(c_clusters) do
if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
if cluster.noise_settings.type == "connected_tendril" then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
insert(rocks, {name = 'rock-huge', position = position})
huge_rock_inserted = true
end
end
elseif cluster.noise_settings.type == "fragmented_tendril" then
local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold
and -1 * cluster.noise_settings.discriminator_threshold < noise2
and noise2 < cluster.noise_settings.discriminator_threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
insert(rocks, {name = 'rock-huge', position = position})
huge_rock_inserted = true
end
end
else
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if noise >= cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
insert(rocks, {name = 'rock-huge', position = position})
huge_rock_inserted = true
end
end
end
end
end
end
if (huge_rock_inserted == false) then
insert(rocks, {name = 'sand-rock-big', position = position})
end
end
Template.insert(surface, tiles, rocks)
end
local artificial_tiles = {
['stone-brick'] = true,
['stone-path'] = true,
['concrete'] = true,
['hazard-concrete-left'] = true,
['hazard-concrete-right'] = true,
['refined-concrete'] = true,
['refined-hazard-concrete-left'] = true,
['refined-hazard-concrete-right'] = true,
}
local function on_mined_tile(surface, tiles)
local new_tiles = {}
for _, tile in pairs(tiles) do
if (artificial_tiles[tile.old_tile.name]) then
insert(new_tiles, { name = 'dirt-' .. random(1, 7), position = tile.position})
end
end
Template.insert(surface, new_tiles, {})
end
--[[--
Registers all event handlers.
]]
function DiggyHole.register(config)
ScoreTable.reset('Void removed')
Event.add(defines.events.on_entity_died, function (event)
diggy_hole(event.entity)
end)
local enable_digging_warning = config.enable_digging_warning
Event.add(defines.events.on_player_mined_entity, function (event)
local entity = event.entity
local name = entity.name
if name == 'sand-rock-big' or name == 'rock-huge' then
event.buffer.remove({name = 'coal', count = 100})
-- this logic can be replaced once we've fully replaced the stone to surface functionality
if enable_digging_warning then
local player = Game.get_player_by_index(event.player_index)
if player and player.valid then
if player.get_main_inventory().can_insert({name = 'stone'}) then
reset_player_full_inventory_cache(player)
else
trigger_inventory_warning(player)
end
end
end
end
diggy_hole(entity)
end)
Event.add(defines.events.on_robot_mined_tile, function (event)
on_mined_tile(event.robot.surface, event.tiles)
end)
Event.add(defines.events.on_player_mined_tile, function (event)
on_mined_tile(game.surfaces[event.surface_index], event.tiles)
end)
Event.add(Template.events.on_void_removed, function ()
ScoreTable.increment('Void removed')
end)
if config.enable_debug_commands then
commands.add_command('clear-void', '<left top x> <left top y> <width> <height> <surface index> triggers Template.insert for the given area.', function(cmd)
local params = {}
local args = cmd.parameter or ''
for param in string.gmatch(args, '%S+') do
table.insert(params, param)
end
if (#params ~= 5) then
game.player.print('/clear-void requires exactly 5 arguments: <left top x> <left top y> <width> <height> <surface index>')
return
end
local left_top_x = tonumber(params[1])
local left_top_y = tonumber(params[2])
local width = tonumber(params[3])
local height = tonumber(params[4])
local surface_index = params[5]
local tiles = {}
local entities = {}
for x = 0, width do
for y = 0, height do
insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x + left_top_x, y = y + left_top_y}})
end
end
Template.insert(game.surfaces[surface_index], tiles, entities)
end
)
end
end
function DiggyHole.on_init()
game.forces.player.technologies['landfill'].enabled = false
end
return DiggyHole

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,40 @@
--[[-- info
Provides the ability to refresh the map and generate darkness.
]]
-- dependencies
local Event = require 'utils.event'
local insert = table.insert
-- this
local RefreshMap = {}
--[[--
Registers all event handlers.
]]
function RefreshMap.register(config)
Event.add(defines.events.on_chunk_generated, function (event)
local tiles = {}
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local target_x = event.area.left_top.x + x
local target_y = event.area.left_top.y + y
local tile = 'out-of-map'
if (target_x < 1 and target_y < 1 and target_x > -2 and target_y > -2) then
tile = 'lab-dark-1'
end
insert(tiles, {
name = tile,
position = {x = target_x, y = target_y}
})
end
end
event.surface.set_tiles(tiles)
end)
end
return RefreshMap
--[[-- info
Provides the ability to refresh the map and generate darkness.
]]
-- dependencies
local Event = require 'utils.event'
local insert = table.insert
-- this
local RefreshMap = {}
--[[--
Registers all event handlers.
]]
function RefreshMap.register(config)
Event.add(defines.events.on_chunk_generated, function (event)
local tiles = {}
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local target_x = event.area.left_top.x + x
local target_y = event.area.left_top.y + y
local tile = 'out-of-map'
if (target_x < 1 and target_y < 1 and target_x > -2 and target_y > -2) then
tile = 'lab-dark-1'
end
insert(tiles, {
name = tile,
position = {x = target_x, y = target_y}
})
end
end
event.surface.set_tiles(tiles)
end)
end
return RefreshMap

View File

@ -1,262 +1,262 @@
--[[-- info
Provides the ability to spawn random ores all over the place.
]]
-- dependencies
local Event = require 'utils.event'
local Debug = require 'map_gen.Diggy.Debug'
local Template = require 'map_gen.Diggy.Template'
local Perlin = require 'map_gen.shared.perlin_noise'
local Simplex = require 'map_gen.shared.simplex_noise'
local random = math.random
local sqrt = math.sqrt
local ceil = math.ceil
local floor = math.floor
-- this
local ScatteredResources = {}
local function get_name_by_weight(collection, sum)
local pre_calculated = random()
local current = 0
local target = pre_calculated * sum
for name, weight in pairs(collection) do
current = current + weight
if (current >= target) then
return name
end
end
Debug.print('Current \'' .. current .. '\' should be higher or equal to random \'' .. target .. '\'')
end
--[[--
Registers all event handlers.
]]
function ScatteredResources.register(config)
-- source of noise for resource generation
-- index determines offset
-- '-1' is reserved for cluster mode
-- compound clusters use as many indexes as needed > 1
local base_seed
local function seeded_noise(surface, x, y, index, sources)
base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
local noise = 0
for _, settings in ipairs(sources) do
settings.type = settings.type or 'perlin'
settings.offset = settings.offset or 0
if settings.type == 'zero' then
noise = noise + 0
elseif settings.type == 'one' then
noise = noise + settings.weight * 1
elseif settings.type == 'perlin' then
noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
elseif settings.type == 'simplex' then
noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
else
Debug.print('noise type \'' .. settings.type .. '\' not recognized')
end
end
return noise
end
-- global config values
local resource_richness_weights = config.resource_richness_weights
local resource_richness_weights_sum = 0
for _, weight in pairs(resource_richness_weights) do
resource_richness_weights_sum = resource_richness_weights_sum + weight
end
local resource_richness_values = config.resource_richness_values
local resource_type_scalar = config.resource_type_scalar
-- scattered config values
local s_mode = config.scattered_mode
local s_dist_mod = config.scattered_distance_probability_modifier
local s_min_prob = config.scattered_min_probability
local s_max_prob = config.scattered_max_probability
local s_dist_richness = config.scattered_distance_richness_modifier
local s_cluster_prob = config.scattered_cluster_probability_multiplier
local s_cluster_mult = config.scattered_cluster_yield_multiplier
local s_resource_weights = config.scattered_resource_weights
local s_resource_weights_sum = 0
for _, weight in pairs(s_resource_weights) do
s_resource_weights_sum = s_resource_weights_sum + weight
end
local s_min_dist = config.scattered_minimum_resource_distance
-- cluster config values
local cluster_mode = config.cluster_mode
-- compound cluster spawning
local c_mode = config.cluster_mode
local c_clusters = require(config.cluster_file_location)
if ('table' ~= type(c_clusters)) then
error('cluster_file_location invalid')
end
local c_count = 0
for _, cluster in ipairs(c_clusters) do
c_count = c_count + 1
cluster.weights_sum = 0
-- ensure the cluster colors are valid otherwise it fails silently
-- and breaks things elsewhere
if cluster.color then
local c = cluster.color
if (not c.r) or (not c.g) or (not c.b) then
cluster.color = nil
elseif c.r < 0 or c.r > 1 or c.g < 0 or c.g > 1 or c.b < 0 or c.b > 1 then
cluster.color = nil
end
end
for _, weight in pairs(cluster.weights) do
cluster.weights_sum = cluster.weights_sum + weight
end
end
local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
local distance = sqrt(x * x + y * y)
local resource_name = get_name_by_weight(cluster.weights, cluster.weights_sum)
if resource_name == 'skip' then
return false
end
if cluster.distances[resource_name] then
if distance < cluster.distances[resource_name] then
return false
end
end
local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
local amount = random(range[1], range[2])
amount = amount * (1 + ((distance / cluster.distance_richness) * 0.01))
amount = amount * cluster.yield
if resource_type_scalar[resource_name] then
amount = amount * resource_type_scalar[resource_name]
end
Template.resources(surface, {{name = resource_name, position = {x = x, y = y}, amount = ceil(amount)}})
return true
end
-- event registration
Event.add(Template.events.on_void_removed, function (event)
local position = event.position
local x = position.x
local y = position.y
local surface = event.surface
local distance = config.distance(x, y)
if c_mode then
for index,cluster in ipairs(c_clusters) do
if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
if cluster.noise_settings.type == "connected_tendril" then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
return -- resource spawned
end
end
elseif cluster.noise_settings.type == "fragmented_tendril" then
local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold
and -1 * cluster.noise_settings.discriminator_threshold < noise2
and noise2 < cluster.noise_settings.discriminator_threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
return -- resource spawned
end
end
else
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if noise >= cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
return -- resource spawned
end
end
end
end
end
end
if s_mode then
local probability = math.min(s_max_prob, s_min_prob + 0.01 * (distance / s_dist_mod))
if (cluster_mode) then
probability = probability * s_cluster_prob
end
if (probability > random()) then
-- spawn single resource point for scatter mode
local resource_name = get_name_by_weight(s_resource_weights, s_resource_weights_sum)
if resource_name == 'skip' or s_min_dist[resource_name] > distance then
return
end
local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
local amount = random(range[1], range[2])
amount = amount * (1 + ((distance / s_dist_richness) * 0.01))
if resource_type_scalar[resource_name] then
amount = amount * resource_type_scalar[resource_name]
end
if (cluster_mode) then
amount = amount * s_cluster_mult
end
Template.resources(surface, {{name = resource_name, position={x=x,y=y}, amount = ceil(amount)}})
end
end
end)
if (config.display_ore_clusters) then
local color = {}
Event.add(defines.events.on_chunk_generated, function (event)
local surface = event.surface
local area = event.area
for x = area.left_top.x, area.left_top.x + 31 do
for y = area.left_top.y, area.left_top.y + 31 do
for index,cluster in ipairs(c_clusters) do
if cluster.noise_settings.type == "connected_tendril" then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
end
elseif cluster.noise_settings.type == "fragmented_tendril" then
local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold
and -1 * cluster.noise_settings.discriminator_threshold < noise2
and noise2 < cluster.noise_settings.discriminator_threshold then
color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
end
elseif cluster.noise_settings.type ~= 'skip' then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if noise >= cluster.noise_settings.threshold then
color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
end
end
end
end
end
end)
end
end
function ScatteredResources.get_extra_map_info(config)
return [[Scattered Resources, resources are everywhere!
Scans of the mine have shown greater amounts of resources to be deeper in the mine]]
end
return ScatteredResources
--[[-- info
Provides the ability to spawn random ores all over the place.
]]
-- dependencies
local Event = require 'utils.event'
local Debug = require 'map_gen.Diggy.Debug'
local Template = require 'map_gen.Diggy.Template'
local Perlin = require 'map_gen.shared.perlin_noise'
local Simplex = require 'map_gen.shared.simplex_noise'
local random = math.random
local sqrt = math.sqrt
local ceil = math.ceil
local floor = math.floor
-- this
local ScatteredResources = {}
local function get_name_by_weight(collection, sum)
local pre_calculated = random()
local current = 0
local target = pre_calculated * sum
for name, weight in pairs(collection) do
current = current + weight
if (current >= target) then
return name
end
end
Debug.print('Current \'' .. current .. '\' should be higher or equal to random \'' .. target .. '\'')
end
--[[--
Registers all event handlers.
]]
function ScatteredResources.register(config)
-- source of noise for resource generation
-- index determines offset
-- '-1' is reserved for cluster mode
-- compound clusters use as many indexes as needed > 1
local base_seed
local function seeded_noise(surface, x, y, index, sources)
base_seed = base_seed or surface.map_gen_settings.seed + surface.index + 4000
local noise = 0
for _, settings in ipairs(sources) do
settings.type = settings.type or 'perlin'
settings.offset = settings.offset or 0
if settings.type == 'zero' then
noise = noise + 0
elseif settings.type == 'one' then
noise = noise + settings.weight * 1
elseif settings.type == 'perlin' then
noise = noise + settings.weight * Perlin.noise(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
elseif settings.type == 'simplex' then
noise = noise + settings.weight * Simplex.d2(x/settings.variance, y/settings.variance,
base_seed + 2000*index + settings.offset)
else
Debug.print('noise type \'' .. settings.type .. '\' not recognized')
end
end
return noise
end
-- global config values
local resource_richness_weights = config.resource_richness_weights
local resource_richness_weights_sum = 0
for _, weight in pairs(resource_richness_weights) do
resource_richness_weights_sum = resource_richness_weights_sum + weight
end
local resource_richness_values = config.resource_richness_values
local resource_type_scalar = config.resource_type_scalar
-- scattered config values
local s_mode = config.scattered_mode
local s_dist_mod = config.scattered_distance_probability_modifier
local s_min_prob = config.scattered_min_probability
local s_max_prob = config.scattered_max_probability
local s_dist_richness = config.scattered_distance_richness_modifier
local s_cluster_prob = config.scattered_cluster_probability_multiplier
local s_cluster_mult = config.scattered_cluster_yield_multiplier
local s_resource_weights = config.scattered_resource_weights
local s_resource_weights_sum = 0
for _, weight in pairs(s_resource_weights) do
s_resource_weights_sum = s_resource_weights_sum + weight
end
local s_min_dist = config.scattered_minimum_resource_distance
-- cluster config values
local cluster_mode = config.cluster_mode
-- compound cluster spawning
local c_mode = config.cluster_mode
local c_clusters = require(config.cluster_file_location)
if ('table' ~= type(c_clusters)) then
error('cluster_file_location invalid')
end
local c_count = 0
for _, cluster in ipairs(c_clusters) do
c_count = c_count + 1
cluster.weights_sum = 0
-- ensure the cluster colors are valid otherwise it fails silently
-- and breaks things elsewhere
if cluster.color then
local c = cluster.color
if (not c.r) or (not c.g) or (not c.b) then
cluster.color = nil
elseif c.r < 0 or c.r > 1 or c.g < 0 or c.g > 1 or c.b < 0 or c.b > 1 then
cluster.color = nil
end
end
for _, weight in pairs(cluster.weights) do
cluster.weights_sum = cluster.weights_sum + weight
end
end
local function spawn_cluster_resource(surface, x, y, cluster_index, cluster)
local distance = sqrt(x * x + y * y)
local resource_name = get_name_by_weight(cluster.weights, cluster.weights_sum)
if resource_name == 'skip' then
return false
end
if cluster.distances[resource_name] then
if distance < cluster.distances[resource_name] then
return false
end
end
local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
local amount = random(range[1], range[2])
amount = amount * (1 + ((distance / cluster.distance_richness) * 0.01))
amount = amount * cluster.yield
if resource_type_scalar[resource_name] then
amount = amount * resource_type_scalar[resource_name]
end
Template.resources(surface, {{name = resource_name, position = {x = x, y = y}, amount = ceil(amount)}})
return true
end
-- event registration
Event.add(Template.events.on_void_removed, function (event)
local position = event.position
local x = position.x
local y = position.y
local surface = event.surface
local distance = config.distance(x, y)
if c_mode then
for index,cluster in ipairs(c_clusters) do
if distance >= cluster.min_distance and cluster.noise_settings.type ~= 'skip' then
if cluster.noise_settings.type == "connected_tendril" then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
return -- resource spawned
end
end
elseif cluster.noise_settings.type == "fragmented_tendril" then
local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold
and -1 * cluster.noise_settings.discriminator_threshold < noise2
and noise2 < cluster.noise_settings.discriminator_threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
return -- resource spawned
end
end
else
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if noise >= cluster.noise_settings.threshold then
if spawn_cluster_resource(surface, x, y, index, cluster) then
return -- resource spawned
end
end
end
end
end
end
if s_mode then
local probability = math.min(s_max_prob, s_min_prob + 0.01 * (distance / s_dist_mod))
if (cluster_mode) then
probability = probability * s_cluster_prob
end
if (probability > random()) then
-- spawn single resource point for scatter mode
local resource_name = get_name_by_weight(s_resource_weights, s_resource_weights_sum)
if resource_name == 'skip' or s_min_dist[resource_name] > distance then
return
end
local range = resource_richness_values[get_name_by_weight(resource_richness_weights, resource_richness_weights_sum)]
local amount = random(range[1], range[2])
amount = amount * (1 + ((distance / s_dist_richness) * 0.01))
if resource_type_scalar[resource_name] then
amount = amount * resource_type_scalar[resource_name]
end
if (cluster_mode) then
amount = amount * s_cluster_mult
end
Template.resources(surface, {{name = resource_name, position={x=x,y=y}, amount = ceil(amount)}})
end
end
end)
if (config.display_ore_clusters) then
local color = {}
Event.add(defines.events.on_chunk_generated, function (event)
local surface = event.surface
local area = event.area
for x = area.left_top.x, area.left_top.x + 31 do
for y = area.left_top.y, area.left_top.y + 31 do
for index,cluster in ipairs(c_clusters) do
if cluster.noise_settings.type == "connected_tendril" then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if -1 * cluster.noise_settings.threshold < noise and noise < cluster.noise_settings.threshold then
color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
end
elseif cluster.noise_settings.type == "fragmented_tendril" then
local noise1 = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
local noise2 = seeded_noise(surface, x, y, index, cluster.noise_settings.discriminator)
if -1 * cluster.noise_settings.threshold < noise1 and noise1 < cluster.noise_settings.threshold
and -1 * cluster.noise_settings.discriminator_threshold < noise2
and noise2 < cluster.noise_settings.discriminator_threshold then
color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
end
elseif cluster.noise_settings.type ~= 'skip' then
local noise = seeded_noise(surface, x, y, index, cluster.noise_settings.sources)
if noise >= cluster.noise_settings.threshold then
color[index] = color[index] or cluster.color or {r=random(), g=random(), b=random()}
Debug.print_colored_grid_value('o' .. index, surface, {x = x, y = y}, nil, nil, true, 0, color[index])
end
end
end
end
end
end)
end
end
function ScatteredResources.get_extra_map_info(config)
return [[Scattered Resources, resources are everywhere!
Scans of the mine have shown greater amounts of resources to be deeper in the mine]]
end
return ScatteredResources

View File

@ -1,53 +1,53 @@
--[[-- info
Provides the ability to setup a player when first joined.
]]
-- dependencies
local Event = require 'utils.event'
local Debug = require 'map_gen.Diggy.Debug'
local Game = require 'utils.game'
-- this
local SetupPlayer = {}
global.SetupPlayer = {
first_player_spawned = false,
}
--[[--
Registers all event handlers.
]]
function SetupPlayer.register(config)
Event.add(defines.events.on_player_created, function (event)
local player = Game.get_player_by_index(event.player_index)
local player_insert = player.insert
local position = {0, 0}
local surface = player.surface
for _, item in pairs(config.starting_items) do
player_insert(item)
end
if (global.SetupPlayer.first_player_spawned) then
position = surface.find_non_colliding_position('player', position, 3, 0.1)
else
global.SetupPlayer.first_player_spawned = true
end
player.force.set_spawn_position(position, surface)
player.teleport(position)
Debug.cheat(function()
local cheats = config.cheats
player.force.manual_mining_speed_modifier = cheats.manual_mining_speed_modifier
player.force.character_inventory_slots_bonus = cheats.character_inventory_slots_bonus
player.force.character_running_speed_modifier = cheats.character_running_speed_modifier
for _, item in pairs(cheats.starting_items) do
player_insert(item)
end
end)
end)
end
return SetupPlayer
--[[-- info
Provides the ability to setup a player when first joined.
]]
-- dependencies
local Event = require 'utils.event'
local Debug = require 'map_gen.Diggy.Debug'
local Game = require 'utils.game'
-- this
local SetupPlayer = {}
global.SetupPlayer = {
first_player_spawned = false,
}
--[[--
Registers all event handlers.
]]
function SetupPlayer.register(config)
Event.add(defines.events.on_player_created, function (event)
local player = Game.get_player_by_index(event.player_index)
local player_insert = player.insert
local position = {0, 0}
local surface = player.surface
for _, item in pairs(config.starting_items) do
player_insert(item)
end
if (global.SetupPlayer.first_player_spawned) then
position = surface.find_non_colliding_position('player', position, 3, 0.1)
else
global.SetupPlayer.first_player_spawned = true
end
player.force.set_spawn_position(position, surface)
player.teleport(position)
Debug.cheat(function()
local cheats = config.cheats
player.force.manual_mining_speed_modifier = cheats.manual_mining_speed_modifier
player.force.character_inventory_slots_bonus = cheats.character_inventory_slots_bonus
player.force.character_running_speed_modifier = cheats.character_running_speed_modifier
for _, item in pairs(cheats.starting_items) do
player_insert(item)
end
end)
end)
end
return SetupPlayer

View File

@ -1,108 +1,108 @@
--[[-- info
Provides the ability to make a simple room with contents
]]
-- dependencies
local Template = require 'map_gen.Diggy.Template'
local Perlin = require 'map_gen.shared.perlin_noise'
local Event = require 'utils.event'
local Debug = require'map_gen.Diggy.Debug'
local Task = require 'utils.Task'
local Token = require 'utils.global_token'
local raise_event = script.raise_event
-- this
local SimpleRoomGenerator = {}
local do_spawn_tile = Token.register(function(params)
Template.insert(params.surface, {params.tile}, {})
end)
local do_mine = Token.register(function(params)
local surface = params.surface
local position = params.position
local rocks = surface.find_entities_filtered({ position = position, name = { 'sand-rock-big', 'rock-huge'}})
if (0 == #rocks) then
return
end
for _, rock in pairs(rocks) do
raise_event(defines.events.on_entity_died, {entity = rock})
rock.destroy()
end
end)
local function handle_noise(name, surface, position)
Task.set_timeout_in_ticks(1, do_mine, {surface = surface, position = position})
if ('water' == name) then
-- water is slower because for some odd reason it doesn't always want to mine it properly
Task.set_timeout_in_ticks(4, do_spawn_tile, { surface = surface, tile = { name = 'deepwater-green', position = position}})
return
end
if ('dirt' == name) then
return
end
error('No noise handled for type \'' .. name .. '\'')
end
--[[--
Registers all event handlers.
]]
function SimpleRoomGenerator.register(config)
local room_noise_minimum_distance_sq = config.room_noise_minimum_distance * config.room_noise_minimum_distance
local seed
local function get_noise(surface, x, y)
seed = seed or surface.map_gen_settings.seed + surface.index + 100
return Perlin.noise(x * config.noise_variance, y * config.noise_variance, seed)
end
Event.add(Template.events.on_void_removed, function (event)
local position = event.position
local x = position.x
local y = position.y
local distance_sq = x * x + y * y
if (distance_sq <= room_noise_minimum_distance_sq) then
return
end
local surface = event.surface
local noise = get_noise(surface, x, y)
for _, noise_range in pairs(config.room_noise_ranges) do
if (noise >= noise_range.min and noise <= noise_range.max) then
handle_noise(noise_range.name, surface, position)
end
end
end)
if (config.display_room_locations) then
Event.add(defines.events.on_chunk_generated, function (event)
local surface = event.surface
local area = event.area
for x = area.left_top.x, area.left_top.x + 31 do
for y = area.left_top.y, area.left_top.y + 31 do
for _, noise_range in pairs(config.room_noise_ranges) do
local noise = get_noise(surface, x, y)
if (noise >= noise_range.min and noise <= noise_range.max) then
Debug.print_grid_value(noise_range.name, surface, {x = x, y = y}, nil, nil, true)
end
end
end
end
end)
end
end
function SimpleRoomGenerator.get_extra_map_info(config)
return 'Simple Room Generator, digging around might open rooms!'
end
return SimpleRoomGenerator
--[[-- info
Provides the ability to make a simple room with contents
]]
-- dependencies
local Template = require 'map_gen.Diggy.Template'
local Perlin = require 'map_gen.shared.perlin_noise'
local Event = require 'utils.event'
local Debug = require'map_gen.Diggy.Debug'
local Task = require 'utils.Task'
local Token = require 'utils.global_token'
local raise_event = script.raise_event
-- this
local SimpleRoomGenerator = {}
local do_spawn_tile = Token.register(function(params)
Template.insert(params.surface, {params.tile}, {})
end)
local do_mine = Token.register(function(params)
local surface = params.surface
local position = params.position
local rocks = surface.find_entities_filtered({ position = position, name = { 'sand-rock-big', 'rock-huge'}})
if (0 == #rocks) then
return
end
for _, rock in pairs(rocks) do
raise_event(defines.events.on_entity_died, {entity = rock})
rock.destroy()
end
end)
local function handle_noise(name, surface, position)
Task.set_timeout_in_ticks(1, do_mine, {surface = surface, position = position})
if ('water' == name) then
-- water is slower because for some odd reason it doesn't always want to mine it properly
Task.set_timeout_in_ticks(4, do_spawn_tile, { surface = surface, tile = { name = 'deepwater-green', position = position}})
return
end
if ('dirt' == name) then
return
end
error('No noise handled for type \'' .. name .. '\'')
end
--[[--
Registers all event handlers.
]]
function SimpleRoomGenerator.register(config)
local room_noise_minimum_distance_sq = config.room_noise_minimum_distance * config.room_noise_minimum_distance
local seed
local function get_noise(surface, x, y)
seed = seed or surface.map_gen_settings.seed + surface.index + 100
return Perlin.noise(x * config.noise_variance, y * config.noise_variance, seed)
end
Event.add(Template.events.on_void_removed, function (event)
local position = event.position
local x = position.x
local y = position.y
local distance_sq = x * x + y * y
if (distance_sq <= room_noise_minimum_distance_sq) then
return
end
local surface = event.surface
local noise = get_noise(surface, x, y)
for _, noise_range in pairs(config.room_noise_ranges) do
if (noise >= noise_range.min and noise <= noise_range.max) then
handle_noise(noise_range.name, surface, position)
end
end
end)
if (config.display_room_locations) then
Event.add(defines.events.on_chunk_generated, function (event)
local surface = event.surface
local area = event.area
for x = area.left_top.x, area.left_top.x + 31 do
for y = area.left_top.y, area.left_top.y + 31 do
for _, noise_range in pairs(config.room_noise_ranges) do
local noise = get_noise(surface, x, y)
if (noise >= noise_range.min and noise <= noise_range.max) then
Debug.print_grid_value(noise_range.name, surface, {x = x, y = y}, nil, nil, true)
end
end
end
end
end)
end
end
function SimpleRoomGenerator.get_extra_map_info(config)
return 'Simple Room Generator, digging around might open rooms!'
end
return SimpleRoomGenerator

View File

@ -1,81 +1,81 @@
--[[-- info
Provides the ability to create a pre-configured starting zone.
]]
-- dependencies
local Event = require 'utils.event'
local Token = require 'utils.global_token'
local Template = require 'map_gen.Diggy.Template'
local Debug = require 'map_gen.Diggy.Debug'
local DiggyCaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
local insert = table.insert
local random = math.random
local sqrt = math.sqrt
local floor = math.floor
-- this
local StartingZone = {}
--[[--
Registers all event handlers.
]]
function StartingZone.register(config)
local callback_token
local starting_zone_size = config.starting_size
local function on_chunk_generated(event)
local start_point_area = {{-0.9, -0.9}, {0.9, 0.9}}
local start_point_cleanup = {{-0.9, -0.9}, {1.9, 1.9}}
local surface = event.surface
-- hack to figure out whether the important chunks are generated via Diggy.Feature.RefreshMap.
if (4 ~= surface.count_tiles_filtered({start_point_area, name = 'lab-dark-1'})) then
return
end
-- ensure a clean starting point
for _, entity in pairs(surface.find_entities_filtered({area = start_point_cleanup, type = 'resource'})) do
entity.destroy()
end
local tiles = {}
local rocks = {}
local dirt_range = floor(starting_zone_size * 0.5)
local rock_range = starting_zone_size - 2
local stress_hack = floor(starting_zone_size * 0.1)
for x = -starting_zone_size, starting_zone_size do
for y = -starting_zone_size, starting_zone_size do
local distance = floor(sqrt(x * x + y * y))
if (distance < starting_zone_size) then
if (distance > dirt_range) then
insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x, y = y}})
else
insert(tiles, {name = 'stone-path', position = {x = x, y = y}})
end
if (distance > rock_range) then
insert(rocks, {name = 'sand-rock-big', position = {x = x, y = y}})
end
-- hack to avoid starting area from collapsing
if (distance > stress_hack) then
DiggyCaveCollapse.stress_map_add(surface, {x = x, y = y}, -0.5)
end
end
end
end
Template.insert(event.surface, tiles, rocks)
Event.remove_removable(defines.events.on_chunk_generated, callback_token)
end
callback_token = Token.register(on_chunk_generated)
Event.add_removable(defines.events.on_chunk_generated, callback_token)
end
return StartingZone
--[[-- info
Provides the ability to create a pre-configured starting zone.
]]
-- dependencies
local Event = require 'utils.event'
local Token = require 'utils.global_token'
local Template = require 'map_gen.Diggy.Template'
local Debug = require 'map_gen.Diggy.Debug'
local DiggyCaveCollapse = require 'map_gen.Diggy.Feature.DiggyCaveCollapse'
local insert = table.insert
local random = math.random
local sqrt = math.sqrt
local floor = math.floor
-- this
local StartingZone = {}
--[[--
Registers all event handlers.
]]
function StartingZone.register(config)
local callback_token
local starting_zone_size = config.starting_size
local function on_chunk_generated(event)
local start_point_area = {{-0.9, -0.9}, {0.9, 0.9}}
local start_point_cleanup = {{-0.9, -0.9}, {1.9, 1.9}}
local surface = event.surface
-- hack to figure out whether the important chunks are generated via Diggy.Feature.RefreshMap.
if (4 ~= surface.count_tiles_filtered({start_point_area, name = 'lab-dark-1'})) then
return
end
-- ensure a clean starting point
for _, entity in pairs(surface.find_entities_filtered({area = start_point_cleanup, type = 'resource'})) do
entity.destroy()
end
local tiles = {}
local rocks = {}
local dirt_range = floor(starting_zone_size * 0.5)
local rock_range = starting_zone_size - 2
local stress_hack = floor(starting_zone_size * 0.1)
for x = -starting_zone_size, starting_zone_size do
for y = -starting_zone_size, starting_zone_size do
local distance = floor(sqrt(x * x + y * y))
if (distance < starting_zone_size) then
if (distance > dirt_range) then
insert(tiles, {name = 'dirt-' .. random(1, 7), position = {x = x, y = y}})
else
insert(tiles, {name = 'stone-path', position = {x = x, y = y}})
end
if (distance > rock_range) then
insert(rocks, {name = 'sand-rock-big', position = {x = x, y = y}})
end
-- hack to avoid starting area from collapsing
if (distance > stress_hack) then
DiggyCaveCollapse.stress_map_add(surface, {x = x, y = y}, -0.5)
end
end
end
end
Template.insert(event.surface, tiles, rocks)
Event.remove_removable(defines.events.on_chunk_generated, callback_token)
end
callback_token = Token.register(on_chunk_generated)
Event.add_removable(defines.events.on_chunk_generated, callback_token)
end
return StartingZone

View File

@ -1,3 +1,3 @@
## RedMew - Diggy, Custom Scenario
The documentation for Diggy has moved to [docs/scenarios/Diggy.md](../../docs/scenarios/Diggy.md).
## RedMew - Diggy, Custom Scenario
The documentation for Diggy has moved to [docs/scenarios/Diggy.md](../../docs/scenarios/Diggy.md).

View File

@ -1,42 +1,42 @@
-- dependencies
local insert = table.insert
-- this
local Scanner = {}
--[[--
returns a list with all direct positions that contain tile_search.
@param surface LuaSurface
@param position Position
@param tile_search string name of the tile to search for
@return table with 0~4 directions of which have the tile searched for adjacent
]]
function Scanner.scan_around_position(surface, position, tile_search)
local tile_found = {}
local get_tile = surface.get_tile
-- north
if (tile_search == get_tile(position.x, position.y - 1).name) then
insert(tile_found, {x = position.x, y = position.y - 1})
end
-- east
if (tile_search == get_tile(position.x + 1, position.y).name) then
insert(tile_found, {x = position.x + 1, y = position.y})
end
-- south
if (tile_search == get_tile(position.x, position.y + 1).name) then
insert(tile_found, {x = position.x, y = position.y + 1})
end
-- west
if (tile_search == get_tile(position.x - 1, position.y).name) then
insert(tile_found, {x = position.x - 1, y = position.y})
end
return tile_found;
end
return Scanner
-- dependencies
local insert = table.insert
-- this
local Scanner = {}
--[[--
returns a list with all direct positions that contain tile_search.
@param surface LuaSurface
@param position Position
@param tile_search string name of the tile to search for
@return table with 0~4 directions of which have the tile searched for adjacent
]]
function Scanner.scan_around_position(surface, position, tile_search)
local tile_found = {}
local get_tile = surface.get_tile
-- north
if (tile_search == get_tile(position.x, position.y - 1).name) then
insert(tile_found, {x = position.x, y = position.y - 1})
end
-- east
if (tile_search == get_tile(position.x + 1, position.y).name) then
insert(tile_found, {x = position.x + 1, y = position.y})
end
-- south
if (tile_search == get_tile(position.x, position.y + 1).name) then
insert(tile_found, {x = position.x, y = position.y + 1})
end
-- west
if (tile_search == get_tile(position.x - 1, position.y).name) then
insert(tile_found, {x = position.x - 1, y = position.y})
end
return tile_found;
end
return Scanner

View File

@ -1,96 +1,96 @@
-- dependencies
local Config = require 'map_gen.Diggy.Config'
local Debug = require 'map_gen.Diggy.Debug'
local ScenarioInfo = require 'features.gui.info'
local Event = require 'utils.event'
require 'utils.list_utils'
require 'utils.utils'
-- this
local Scenario = {}
global.diggy_scenario_registered = false
--[[--
Allows calling a callback for each enabled feature.
Signature: callback(feature_name, Table feature_data) from {@see Config.features}.
@param if_enabled function to be called if enabled
]]
local function each_enabled_feature(if_enabled)
local type = type(if_enabled)
if ('function' ~= type) then
error('each_enabled_feature expects callback to be a function, given type: ' .. type)
end
for current_name, feature_data in pairs(Config.features) do
if (nil == feature_data.enabled) then
error('Feature ' .. current_name .. ' did not define the enabled property.')
end
if (feature_data.enabled) then
if_enabled(current_name, feature_data)
end
end
end
--[[--
Register the events required to initialize the scenario.
]]
function Scenario.register(debug)
if global.diggy_scenario_registered then
error('Cannot register the Diggy scenario multiple times.')
return
end
global.scenario.config.player_list.enable_coin_col = false
if global.scenario.config then
global.scenario.config.fish_market.enable = nil
end
if ('boolean' == type(debug)) then
Config.Debug = debug
end
if (Config.debug) then
Debug.enable_debug()
end
if (Config.cheats) then
Debug.enable_cheats()
end
local extra_map_info = ''
each_enabled_feature(
function(feature_name, feature_config)
local feature = require ('map_gen.Diggy.Feature.' .. feature_name)
if ('function' ~= type(feature.register)) then
error('Feature ' .. feature_name .. ' did not define a register function.')
end
feature.register(feature_config)
if ('function' == type(feature.get_extra_map_info)) then
extra_map_info = extra_map_info .. feature.get_extra_map_info(feature_config) .. '\n\n'
end
if ('function' == type(feature.on_init)) then
Event.on_init(feature.on_init)
end
end
)
local landfill_tiles = {'dirt-1','dirt-2','dirt-3','dirt-4','dirt-5','dirt-6','dirt-7'}
require ('map_gen.misc.change_landfill_tile')(landfill_tiles)
ScenarioInfo.set_map_name('Diggy')
ScenarioInfo.set_map_description('Dig your way through!')
ScenarioInfo.set_map_extra_info(extra_map_info)
global.diggy_scenario_registered = true
end
return Scenario
-- dependencies
local Config = require 'map_gen.Diggy.Config'
local Debug = require 'map_gen.Diggy.Debug'
local ScenarioInfo = require 'features.gui.info'
local Event = require 'utils.event'
require 'utils.list_utils'
require 'utils.utils'
-- this
local Scenario = {}
global.diggy_scenario_registered = false
--[[--
Allows calling a callback for each enabled feature.
Signature: callback(feature_name, Table feature_data) from {@see Config.features}.
@param if_enabled function to be called if enabled
]]
local function each_enabled_feature(if_enabled)
local type = type(if_enabled)
if ('function' ~= type) then
error('each_enabled_feature expects callback to be a function, given type: ' .. type)
end
for current_name, feature_data in pairs(Config.features) do
if (nil == feature_data.enabled) then
error('Feature ' .. current_name .. ' did not define the enabled property.')
end
if (feature_data.enabled) then
if_enabled(current_name, feature_data)
end
end
end
--[[--
Register the events required to initialize the scenario.
]]
function Scenario.register(debug)
if global.diggy_scenario_registered then
error('Cannot register the Diggy scenario multiple times.')
return
end
global.scenario.config.player_list.enable_coin_col = false
if global.scenario.config then
global.scenario.config.fish_market.enable = nil
end
if ('boolean' == type(debug)) then
Config.Debug = debug
end
if (Config.debug) then
Debug.enable_debug()
end
if (Config.cheats) then
Debug.enable_cheats()
end
local extra_map_info = ''
each_enabled_feature(
function(feature_name, feature_config)
local feature = require ('map_gen.Diggy.Feature.' .. feature_name)
if ('function' ~= type(feature.register)) then
error('Feature ' .. feature_name .. ' did not define a register function.')
end
feature.register(feature_config)
if ('function' == type(feature.get_extra_map_info)) then
extra_map_info = extra_map_info .. feature.get_extra_map_info(feature_config) .. '\n\n'
end
if ('function' == type(feature.on_init)) then
Event.on_init(feature.on_init)
end
end
)
local landfill_tiles = {'dirt-1','dirt-2','dirt-3','dirt-4','dirt-5','dirt-6','dirt-7'}
require ('map_gen.misc.change_landfill_tile')(landfill_tiles)
ScenarioInfo.set_map_name('Diggy')
ScenarioInfo.set_map_description('Dig your way through!')
ScenarioInfo.set_map_extra_info(extra_map_info)
global.diggy_scenario_registered = true
end
return Scenario

View File

@ -1,84 +1,84 @@
-- dependencies
local Global = require 'utils.global'
-- this
local ScoreTable = {}
local scores = {}
Global.register({
scores = scores,
}, function (tbl)
scores = tbl.scores
end)
--[[--
Resets the score 0 for the given name
@param name String
]]
function ScoreTable.reset(name)
scores[name] = 0
end
--[[--
Adds score.
@param name String
@param value int amount to add
@return int the sum for the score added by name
]]
function ScoreTable.add(name, value)
local new = (scores[name] or 0) + value
scores[name] = new
return new
end
--[[--
Increments the score by 1 for name.
@param name String
@return int the sum for the score incremented by name
]]
function ScoreTable.increment(name)
return ScoreTable.add(name, 1)
end
--[[--
Returns the score for a single key.
@param
]]
function ScoreTable.get(name)
return scores[name] or 0
end
--[[--
Returns all scores.
@return table {[string] = int}
]]
function ScoreTable.all()
return scores
end
--[[--
Returns all keys of table scores.
@return table {[string] = name of key}
]]
function ScoreTable.all_keys()
local keyset = {}
local n = 0
for k, v in pairs(scores) do
n = n + 1
keyset[n] = k
end
return keyset
end
return ScoreTable
-- dependencies
local Global = require 'utils.global'
-- this
local ScoreTable = {}
local scores = {}
Global.register({
scores = scores,
}, function (tbl)
scores = tbl.scores
end)
--[[--
Resets the score 0 for the given name
@param name String
]]
function ScoreTable.reset(name)
scores[name] = 0
end
--[[--
Adds score.
@param name String
@param value int amount to add
@return int the sum for the score added by name
]]
function ScoreTable.add(name, value)
local new = (scores[name] or 0) + value
scores[name] = new
return new
end
--[[--
Increments the score by 1 for name.
@param name String
@return int the sum for the score incremented by name
]]
function ScoreTable.increment(name)
return ScoreTable.add(name, 1)
end
--[[--
Returns the score for a single key.
@param
]]
function ScoreTable.get(name)
return scores[name] or 0
end
--[[--
Returns all scores.
@return table {[string] = int}
]]
function ScoreTable.all()
return scores
end
--[[--
Returns all keys of table scores.
@return table {[string] = name of key}
]]
function ScoreTable.all_keys()
local keyset = {}
local n = 0
for k, v in pairs(scores) do
n = n + 1
keyset[n] = k
end
return keyset
end
return ScoreTable

View File

@ -1,216 +1,216 @@
-- dependencies
local Task = require 'utils.Task'
local Token = require 'utils.global_token'
local Debug = require 'map_gen.Diggy.Debug'
local insert = table.insert
local min = math.min
local ceil = math.ceil
local raise_event = script.raise_event
-- this
local Template = {}
local tiles_per_call = 5 --how many tiles are inserted with each call of insert_action
local entities_per_call = 5 --how many entities are inserted with each call of insert_action
Template.events = {
--[[--
When an entity is placed via the template function.
- event.entity LuaEntity
]]
on_placed_entity = script.generate_event_name(),
--[[--
Triggers when an 'out-of-map' tile is replaced by something else.
{surface, old_tile={name, position={x, y}}}
]]
on_void_removed = script.generate_event_name(),
}
local function insert_next_tiles(data)
local void_removed = {}
local surface = data.surface
local get_tile = surface.get_tile
local tiles = {}
pcall(
function()
--use pcall to assure tile_iterator is always incremented, to avoid endless loops
for i = data.tile_iterator, min(data.tile_iterator + tiles_per_call - 1, data.tiles_n) do
local new_tile = data.tiles[i]
insert(tiles, new_tile)
local current_tile = get_tile(new_tile.position.x, new_tile.position.y)
local current_is_void = current_tile.name == 'out-of-map'
local new_is_void = new_tile.name == 'out-of-map'
if (current_is_void and not new_is_void) then
insert(void_removed, {surface = surface, position = current_tile.position})
end
end
end
)
data.tile_iterator = data.tile_iterator + tiles_per_call
surface.set_tiles(tiles)
for _, event in pairs(void_removed) do
raise_event(Template.events.on_void_removed, event)
end
end
local function insert_next_entities(data)
local created_entities = {}
local surface = data.surface
local create_entity = surface.create_entity
pcall(
function()
--use pcall to assure tile_iterator is always incremented, to avoid endless loops
for i = data.entity_iterator, min(data.entity_iterator + entities_per_call - 1, data.entities_n) do
local entity = data.entities[i]
local created_entity = create_entity(entity)
if (nil == created_entity) then
error('Failed creating entity ' .. entity.name .. ' on surface.')
end
insert(created_entities, created_entity)
end
end
)
data.entity_iterator = data.entity_iterator + entities_per_call
for _, entity in pairs(created_entities) do
raise_event(Template.events.on_placed_entity, {entity = entity})
end
return data.entity_iterator <= data.entities_n
end
local function insert_action(data)
if data.tile_iterator <= data.tiles_n then
insert_next_tiles(data)
return true
end
return insert_next_entities(data)
end
local insert_token = Token.register(insert_action)
--[[--
Inserts a batch of tiles and then entities.
@see LuaSurface.set_tiles
@see LuaSurface.entity
@param surface LuaSurface to put the tiles and entities on
@param tiles table of tiles as required by set_tiles
@param entities table of entities as required by create_entity
]]
function Template.insert(surface, tiles, entities)
tiles = tiles or {}
entities = entities or {}
local tiles_n = #tiles
local entities_n = #entities
local total_calls = ceil(tiles_n / tiles_per_call) + (entities_n / entities_per_call)
local data = {
tiles_n = tiles_n,
tile_iterator = 1,
entities_n = entities_n,
entity_iterator = 1,
surface = surface,
tiles = tiles,
entities = entities
}
local continue = true
for i = 1, 4 do
continue = insert_action(data)
if not continue then
return
end
end
if continue then
Task.queue_task(insert_token, data, total_calls - 4)
end
end
--[[--
Designed to spawn aliens, uses find_non_colliding_position.
@see LuaSurface.entity
@param surface LuaSurface to put the tiles and entities on
@param units table of entities as required by create_entity
@param non_colliding_distance int amount of tiles to scan around original position in case it's already taken
@param generic_unit_name_for_spawn_size String allows setting a custom unit name for spawn size, will overwrite the actual
]]
function Template.units(surface, units, non_colliding_distance, generic_unit_name_for_spawn_size)
non_colliding_distance = non_colliding_distance or 1
generic_unit_name_for_spawn_size = generic_unit_name_for_spawn_size or 'player'
local create_entity = surface.create_entity
local position
for _, entity in pairs(units) do
position = position or surface.find_non_colliding_position(
generic_unit_name_for_spawn_size,
entity.position, non_colliding_distance,
0.5
)
if (nil ~= position) then
entity.position = position
create_entity(entity)
elseif (nil == create_entity(entity)) then
Debug.print_position(entity.position, "Failed to spawn '" .. entity.name .. "'")
end
end
end
--[[--
Designed to spawn resources.
@see LuaSurface.entity
@param surface LuaSurface to put the tiles and entities on
@param resources table of entities as required by create_entity
]]
function Template.resources(surface, resources)
local create_entity = surface.create_entity
for _, entity in pairs(resources) do
create_entity(entity)
end
end
--[[--
Designed to spawn a market.
@param surface LuaSurface
@param position Position
@param force LuaForce
@param market_items Table
]]
function Template.market(surface, position, force, market_inventory)
local market = surface.create_entity({name = 'market', position = position})
local add_market_item = market.add_market_item
market.destructible = false
for _, item in ipairs(market_inventory) do
add_market_item(item)
end
force.add_chart_tag(surface, {
text = 'Market',
position = position,
})
raise_event(Template.events.on_placed_entity, {entity = market})
end
return Template
-- dependencies
local Task = require 'utils.Task'
local Token = require 'utils.global_token'
local Debug = require 'map_gen.Diggy.Debug'
local insert = table.insert
local min = math.min
local ceil = math.ceil
local raise_event = script.raise_event
-- this
local Template = {}
local tiles_per_call = 5 --how many tiles are inserted with each call of insert_action
local entities_per_call = 5 --how many entities are inserted with each call of insert_action
Template.events = {
--[[--
When an entity is placed via the template function.
- event.entity LuaEntity
]]
on_placed_entity = script.generate_event_name(),
--[[--
Triggers when an 'out-of-map' tile is replaced by something else.
{surface, old_tile={name, position={x, y}}}
]]
on_void_removed = script.generate_event_name(),
}
local function insert_next_tiles(data)
local void_removed = {}
local surface = data.surface
local get_tile = surface.get_tile
local tiles = {}
pcall(
function()
--use pcall to assure tile_iterator is always incremented, to avoid endless loops
for i = data.tile_iterator, min(data.tile_iterator + tiles_per_call - 1, data.tiles_n) do
local new_tile = data.tiles[i]
insert(tiles, new_tile)
local current_tile = get_tile(new_tile.position.x, new_tile.position.y)
local current_is_void = current_tile.name == 'out-of-map'
local new_is_void = new_tile.name == 'out-of-map'
if (current_is_void and not new_is_void) then
insert(void_removed, {surface = surface, position = current_tile.position})
end
end
end
)
data.tile_iterator = data.tile_iterator + tiles_per_call
surface.set_tiles(tiles)
for _, event in pairs(void_removed) do
raise_event(Template.events.on_void_removed, event)
end
end
local function insert_next_entities(data)
local created_entities = {}
local surface = data.surface
local create_entity = surface.create_entity
pcall(
function()
--use pcall to assure tile_iterator is always incremented, to avoid endless loops
for i = data.entity_iterator, min(data.entity_iterator + entities_per_call - 1, data.entities_n) do
local entity = data.entities[i]
local created_entity = create_entity(entity)
if (nil == created_entity) then
error('Failed creating entity ' .. entity.name .. ' on surface.')
end
insert(created_entities, created_entity)
end
end
)
data.entity_iterator = data.entity_iterator + entities_per_call
for _, entity in pairs(created_entities) do
raise_event(Template.events.on_placed_entity, {entity = entity})
end
return data.entity_iterator <= data.entities_n
end
local function insert_action(data)
if data.tile_iterator <= data.tiles_n then
insert_next_tiles(data)
return true
end
return insert_next_entities(data)
end
local insert_token = Token.register(insert_action)
--[[--
Inserts a batch of tiles and then entities.
@see LuaSurface.set_tiles
@see LuaSurface.entity
@param surface LuaSurface to put the tiles and entities on
@param tiles table of tiles as required by set_tiles
@param entities table of entities as required by create_entity
]]
function Template.insert(surface, tiles, entities)
tiles = tiles or {}
entities = entities or {}
local tiles_n = #tiles
local entities_n = #entities
local total_calls = ceil(tiles_n / tiles_per_call) + (entities_n / entities_per_call)
local data = {
tiles_n = tiles_n,
tile_iterator = 1,
entities_n = entities_n,
entity_iterator = 1,
surface = surface,
tiles = tiles,
entities = entities
}
local continue = true
for i = 1, 4 do
continue = insert_action(data)
if not continue then
return
end
end
if continue then
Task.queue_task(insert_token, data, total_calls - 4)
end
end
--[[--
Designed to spawn aliens, uses find_non_colliding_position.
@see LuaSurface.entity
@param surface LuaSurface to put the tiles and entities on
@param units table of entities as required by create_entity
@param non_colliding_distance int amount of tiles to scan around original position in case it's already taken
@param generic_unit_name_for_spawn_size String allows setting a custom unit name for spawn size, will overwrite the actual
]]
function Template.units(surface, units, non_colliding_distance, generic_unit_name_for_spawn_size)
non_colliding_distance = non_colliding_distance or 1
generic_unit_name_for_spawn_size = generic_unit_name_for_spawn_size or 'player'
local create_entity = surface.create_entity
local position
for _, entity in pairs(units) do
position = position or surface.find_non_colliding_position(
generic_unit_name_for_spawn_size,
entity.position, non_colliding_distance,
0.5
)
if (nil ~= position) then
entity.position = position
create_entity(entity)
elseif (nil == create_entity(entity)) then
Debug.print_position(entity.position, "Failed to spawn '" .. entity.name .. "'")
end
end
end
--[[--
Designed to spawn resources.
@see LuaSurface.entity
@param surface LuaSurface to put the tiles and entities on
@param resources table of entities as required by create_entity
]]
function Template.resources(surface, resources)
local create_entity = surface.create_entity
for _, entity in pairs(resources) do
create_entity(entity)
end
end
--[[--
Designed to spawn a market.
@param surface LuaSurface
@param position Position
@param force LuaForce
@param market_items Table
]]
function Template.market(surface, position, force, market_inventory)
local market = surface.create_entity({name = 'market', position = position})
local add_market_item = market.add_market_item
market.destructible = false
for _, item in ipairs(market_inventory) do
add_market_item(item)
end
force.add_chart_tag(surface, {
text = 'Market',
position = position,
})
raise_event(Template.events.on_placed_entity, {entity = market})
end
return Template

View File

@ -1,2 +1,2 @@
-- authors Linaori, valansch
require 'map_gen.Diggy.Scenario'.register(_DEBUG)
-- authors Linaori, valansch
require 'map_gen.Diggy.Scenario'.register(_DEBUG)

View File

@ -1,191 +1,191 @@
return {
height = 185,
width = 337,
data = {
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
}
return {
height = 185,
width = 337,
data = {
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{1,108,2,16,1,30,2,80,1,29,2,16,1,58,},
{2,10,1,30,2,84,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,195,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,11,1,167,2,5,},
{2,11,1,28,2,85,1,30,2,79,1,31,2,73,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,124,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,17,1,166,2,12,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,80,1,29,2,74,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
{2,11,1,28,2,85,1,30,2,183,},
}
}

View File

@ -1,48 +1,48 @@
local perlin = require 'map_gen.shared.perlin_noise'
local Event = require 'utils.event'
local random_ores = {'iron-ore', 'coal', 'copper-ore', 'stone', 'uranium-ore'}
local random_dense = {1.6, 0.8, 1, 0.6, 0.5} --ore density reference
local function run_ores_module_setup()
local seed = game.surfaces[1].map_gen_settings.seed
if not global.ores_seed_A then
global.ores_seed_A = seed
end
if not global.ores_seed_B then
global.ores_seed_B = seed * 2
end
end
Event.on_init(run_ores_module_setup)
return function(x, y, world)
local d_sq = world.x * world.x + world.y * world.y
if d_sq < 9216 then
return
end
local distance_bonus = 100 + 0.4 * d ^ 1.2
local wiggle = 100 + perlin.noise((x * 0.005), (y * 0.005), global.ores_seed_A + 41) * 60
local Ores_A = perlin.noise((x * 0.01), (y * 0.01), global.ores_seed_B + 57) * wiggle
if Ores_A > 35 then --we place ores
local Ores_B = perlin.noise((x * 0.02), (y * 0.02), global.ores_seed_B + 13) * wiggle
local a = 5
--
if Ores_A < 76 then
a = math.floor(Ores_A * 0.75 + Ores_B * 0.5) % 4 + 1
end --if its not super high we place normal ores
--
local res_amount = distance_bonus
res_amount = math.floor(res_amount * random_dense[a])
--
return {name = random_ores[a], amount = res_amount}
elseif Ores_A < -60 then
if math.random(1, 200) == 1 then
return {name = 'crude-oil', amount = 5000 + math.floor(distance_bonus) * 500}
end
end
end
local perlin = require 'map_gen.shared.perlin_noise'
local Event = require 'utils.event'
local random_ores = {'iron-ore', 'coal', 'copper-ore', 'stone', 'uranium-ore'}
local random_dense = {1.6, 0.8, 1, 0.6, 0.5} --ore density reference
local function run_ores_module_setup()
local seed = game.surfaces[1].map_gen_settings.seed
if not global.ores_seed_A then
global.ores_seed_A = seed
end
if not global.ores_seed_B then
global.ores_seed_B = seed * 2
end
end
Event.on_init(run_ores_module_setup)
return function(x, y, world)
local d_sq = world.x * world.x + world.y * world.y
if d_sq < 9216 then
return
end
local distance_bonus = 100 + 0.4 * d ^ 1.2
local wiggle = 100 + perlin.noise((x * 0.005), (y * 0.005), global.ores_seed_A + 41) * 60
local Ores_A = perlin.noise((x * 0.01), (y * 0.01), global.ores_seed_B + 57) * wiggle
if Ores_A > 35 then --we place ores
local Ores_B = perlin.noise((x * 0.02), (y * 0.02), global.ores_seed_B + 13) * wiggle
local a = 5
--
if Ores_A < 76 then
a = math.floor(Ores_A * 0.75 + Ores_B * 0.5) % 4 + 1
end --if its not super high we place normal ores
--
local res_amount = distance_bonus
res_amount = math.floor(res_amount * random_dense[a])
--
return {name = random_ores[a], amount = res_amount}
elseif Ores_A < -60 then
if math.random(1, 200) == 1 then
return {name = 'crude-oil', amount = 5000 + math.floor(distance_bonus) * 500}
end
end
end

View File

@ -1,178 +1,178 @@
-- Map by Jayefuu, plague006 and grilledham
-- Map in the shape of a maltese cross, with narrow water bridges around the spawn to force "interesting" transfer of materials
local b = require 'map_gen.shared.builders'
local math = require "utils.math"
local degrees = math.rad
local function value(base, mult, pow)
return function(x, y)
local d_sq = x * x + y * y
return base + mult * d_sq ^ (pow / 2) -- d ^ pow
end
end
local function no_trees(world, tile)
if not tile then
return
end
for _, e in ipairs(
world.surface.find_entities_filtered(
{type = 'tree', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
)
) do
e.destroy()
end
return tile
end
local function no_resources(world, tile)
for _, e in ipairs(
world.surface.find_entities_filtered(
{type = 'resource', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
)
) do
e.destroy()
end
return tile
end
local starting_area = 59
local gradient = 0.05
local tiles_half = (starting_area) * 0.5
local function maltese_cross(x,y)
--Create maltese shape
local abs_x = math.abs(x)
local abs_y = math.abs(y)
return not (abs_x > (tiles_half+(abs_y*gradient)) and abs_y > (tiles_half+(abs_x*gradient)))
end
-- create water crossings and pattern
local water_line =
b.any {
b.rectangle(10,8)
}
water_line = b.change_tile(water_line, true, 'water')
local waters = b.single_y_pattern(water_line, 9)
local bounds = b.rectangle(10, starting_area+1)
waters = b.choose(bounds, waters, b.empty_shape)
waters = b.translate(waters,34,0)
local water_pattern = b.any{
waters,
b.rotate(waters,degrees(90)),
b.rotate(waters,degrees(180)),
b.rotate(waters,degrees(270))
}
-- create the starting area as a grass square
local starting_square = b.rectangle(60, 60)
starting_square = b.change_tile(starting_square, true, 'grass-1')
local starting_patch = b.circle(20)
local starting_coal = b.resource(starting_patch, 'coal', value(1800, 0.8, 1.5))
local starting_iron = b.resource(starting_patch, 'iron-ore', value(3000, 0.8, 1.5))
local starting_copper = b.resource(starting_patch, 'copper-ore', value(2200, 0.75, 1.5))
local starting_stone = b.resource(starting_patch, 'stone', value(1100, 0.75, 1.5))
local null = b.no_entity
local starting_resources = b.segment_pattern({null,starting_coal,null,starting_copper,null,starting_stone,null,starting_iron})
starting_resources = b.rotate(starting_resources, degrees(45/2))
-- starting_circle = b.circle(14)
-- ore generation
local patch = b.circle(20)
local small_patch = b.circle(8)
local patches = b.single_pattern(patch, 220, 220)
local stone = b.resource(patch, 'stone', value(100, 0.75, 1.1))
local oil = b.resource(b.throttle_world_xy(small_patch,1,4,1,4), 'crude-oil', value(33000, 50, 1.05))
local coal = b.resource(patch, 'coal', value(100, 0.75, 1.1))
local uranium = b.resource(small_patch, 'uranium-ore', value(200, 0.75, 1.1))
local pattern1 =
{
{stone, oil,stone},
{stone, oil, oil},
{stone, stone, stone}
}
local stone_arm = b.grid_pattern(pattern1, 3, 3, 220,220)
local pattern2 =
{
{coal, coal, coal},
{coal, coal, coal},
{coal, coal, uranium}
}
local coal_arm = b.grid_pattern(pattern2, 3, 3, 220, 220)
local iron = b.resource(patches, 'iron-ore', value(500, 0.8, 1.075))
local copper = b.resource(patches, 'copper-ore', value(400, 0.75, 1.1))
local resources = b.segment_pattern({null,coal_arm,null,copper,null,stone_arm,null,iron})
resources = b.rotate(resources, degrees(45/2))
-- worm islands
local worm_island = b.rectangle(20,300)
local worm_island_end = b.circle(10)
worm_island = b.any{
worm_island_end,
b.translate(worm_island,0,-150),
b.translate(worm_island_end,0,-300)
}
worm_island = b.change_tile(worm_island, true, 'grass-1')
--[[
local worm_names = {
'small-worm-turret',
'medium-worm-turret',
'big-worm-turret'
}
]]--
local max_worm_chance = 64 / 128
local worm_chance_factor = 1 --/ (192 * 512)
local function worms(_, _, world)
local wx, wy = world.x, world.y
local d = math.sqrt(wx * wx + wy * wy)
local worm_chance = d - 20
if worm_chance > 0 then
worm_chance = worm_chance * worm_chance_factor
worm_chance = math.min(worm_chance, max_worm_chance)
if math.random() < worm_chance then
return {name = 'big-worm-turret'}
end
end
end
worm_island = b.apply_entity(worm_island, worms)
worm_island = b.apply_effect(worm_island, no_trees)
local worm_islands = b.any{
b.rotate(b.translate(worm_island,0,-110),degrees(45)),
b.rotate(b.translate(worm_island,0,-110),degrees(45+90)),
b.rotate(b.translate(worm_island,0,-110),degrees(45+180)),
b.rotate(b.translate(worm_island,0,-110),degrees(45+270))
}
-- create the start area using the water and grass square
local start_area =
b.any {
water_pattern,
starting_square
}
-- finalising some bits
start_area = b.apply_entity(start_area, starting_resources) -- adds a different density ore patch to start
maltese_cross = b.change_tile(maltese_cross, true, 'grass-1')
maltese_cross = b.apply_entity(maltese_cross, resources) -- adds our custom ore gen
local sea = b.change_tile(b.full_shape, true, 'water') -- turn the void to water
sea = b.fish(sea, 0.00125) -- feesh!
local map = b.any{worm_islands, start_area, maltese_cross, sea} -- combine everything
map = b.apply_effect(map, no_resources) -- removes vanilla ores
-- Map by Jayefuu, plague006 and grilledham
-- Map in the shape of a maltese cross, with narrow water bridges around the spawn to force "interesting" transfer of materials
local b = require 'map_gen.shared.builders'
local math = require "utils.math"
local degrees = math.rad
local function value(base, mult, pow)
return function(x, y)
local d_sq = x * x + y * y
return base + mult * d_sq ^ (pow / 2) -- d ^ pow
end
end
local function no_trees(world, tile)
if not tile then
return
end
for _, e in ipairs(
world.surface.find_entities_filtered(
{type = 'tree', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
)
) do
e.destroy()
end
return tile
end
local function no_resources(world, tile)
for _, e in ipairs(
world.surface.find_entities_filtered(
{type = 'resource', area = {{world.x, world.y}, {world.x + 1, world.y + 1}}}
)
) do
e.destroy()
end
return tile
end
local starting_area = 59
local gradient = 0.05
local tiles_half = (starting_area) * 0.5
local function maltese_cross(x,y)
--Create maltese shape
local abs_x = math.abs(x)
local abs_y = math.abs(y)
return not (abs_x > (tiles_half+(abs_y*gradient)) and abs_y > (tiles_half+(abs_x*gradient)))
end
-- create water crossings and pattern
local water_line =
b.any {
b.rectangle(10,8)
}
water_line = b.change_tile(water_line, true, 'water')
local waters = b.single_y_pattern(water_line, 9)
local bounds = b.rectangle(10, starting_area+1)
waters = b.choose(bounds, waters, b.empty_shape)
waters = b.translate(waters,34,0)
local water_pattern = b.any{
waters,
b.rotate(waters,degrees(90)),
b.rotate(waters,degrees(180)),
b.rotate(waters,degrees(270))
}
-- create the starting area as a grass square
local starting_square = b.rectangle(60, 60)
starting_square = b.change_tile(starting_square, true, 'grass-1')
local starting_patch = b.circle(20)
local starting_coal = b.resource(starting_patch, 'coal', value(1800, 0.8, 1.5))
local starting_iron = b.resource(starting_patch, 'iron-ore', value(3000, 0.8, 1.5))
local starting_copper = b.resource(starting_patch, 'copper-ore', value(2200, 0.75, 1.5))
local starting_stone = b.resource(starting_patch, 'stone', value(1100, 0.75, 1.5))
local null = b.no_entity
local starting_resources = b.segment_pattern({null,starting_coal,null,starting_copper,null,starting_stone,null,starting_iron})
starting_resources = b.rotate(starting_resources, degrees(45/2))
-- starting_circle = b.circle(14)
-- ore generation
local patch = b.circle(20)
local small_patch = b.circle(8)
local patches = b.single_pattern(patch, 220, 220)
local stone = b.resource(patch, 'stone', value(100, 0.75, 1.1))
local oil = b.resource(b.throttle_world_xy(small_patch,1,4,1,4), 'crude-oil', value(33000, 50, 1.05))
local coal = b.resource(patch, 'coal', value(100, 0.75, 1.1))
local uranium = b.resource(small_patch, 'uranium-ore', value(200, 0.75, 1.1))
local pattern1 =
{
{stone, oil,stone},
{stone, oil, oil},
{stone, stone, stone}
}
local stone_arm = b.grid_pattern(pattern1, 3, 3, 220,220)
local pattern2 =
{
{coal, coal, coal},
{coal, coal, coal},
{coal, coal, uranium}
}
local coal_arm = b.grid_pattern(pattern2, 3, 3, 220, 220)
local iron = b.resource(patches, 'iron-ore', value(500, 0.8, 1.075))
local copper = b.resource(patches, 'copper-ore', value(400, 0.75, 1.1))
local resources = b.segment_pattern({null,coal_arm,null,copper,null,stone_arm,null,iron})
resources = b.rotate(resources, degrees(45/2))
-- worm islands
local worm_island = b.rectangle(20,300)
local worm_island_end = b.circle(10)
worm_island = b.any{
worm_island_end,
b.translate(worm_island,0,-150),
b.translate(worm_island_end,0,-300)
}
worm_island = b.change_tile(worm_island, true, 'grass-1')
--[[
local worm_names = {
'small-worm-turret',
'medium-worm-turret',
'big-worm-turret'
}
]]--
local max_worm_chance = 64 / 128
local worm_chance_factor = 1 --/ (192 * 512)
local function worms(_, _, world)
local wx, wy = world.x, world.y
local d = math.sqrt(wx * wx + wy * wy)
local worm_chance = d - 20
if worm_chance > 0 then
worm_chance = worm_chance * worm_chance_factor
worm_chance = math.min(worm_chance, max_worm_chance)
if math.random() < worm_chance then
return {name = 'big-worm-turret'}
end
end
end
worm_island = b.apply_entity(worm_island, worms)
worm_island = b.apply_effect(worm_island, no_trees)
local worm_islands = b.any{
b.rotate(b.translate(worm_island,0,-110),degrees(45)),
b.rotate(b.translate(worm_island,0,-110),degrees(45+90)),
b.rotate(b.translate(worm_island,0,-110),degrees(45+180)),
b.rotate(b.translate(worm_island,0,-110),degrees(45+270))
}
-- create the start area using the water and grass square
local start_area =
b.any {
water_pattern,
starting_square
}
-- finalising some bits
start_area = b.apply_entity(start_area, starting_resources) -- adds a different density ore patch to start
maltese_cross = b.change_tile(maltese_cross, true, 'grass-1')
maltese_cross = b.apply_entity(maltese_cross, resources) -- adds our custom ore gen
local sea = b.change_tile(b.full_shape, true, 'water') -- turn the void to water
sea = b.fish(sea, 0.00125) -- feesh!
local map = b.any{worm_islands, start_area, maltese_cross, sea} -- combine everything
map = b.apply_effect(map, no_resources) -- removes vanilla ores
return map

View File

@ -1,3 +1,3 @@
return function(x, y, world)
return not (x < -150 or y > 32 or y < -568)
end
return function(x, y, world)
return not (x < -150 or y > 32 or y < -568)
end

View File

@ -1,16 +1,16 @@
local thickness = 72 -- change this to change the spiral thickness.
local inv_pi = 1 / math.pi
local thickness2 = thickness * 2
return function(x, y)
local d_sq = x * x + y * y
if d_sq < 16384 then --d < 128
return true
end
local angle = 1 + inv_pi * math.atan2(x, y)
local offset = d + (angle * thickness)
return offset % thickness2 >= thickness
end
local thickness = 72 -- change this to change the spiral thickness.
local inv_pi = 1 / math.pi
local thickness2 = thickness * 2
return function(x, y)
local d_sq = x * x + y * y
if d_sq < 16384 then --d < 128
return true
end
local angle = 1 + inv_pi * math.atan2(x, y)
local offset = d + (angle * thickness)
return offset % thickness2 >= thickness
end

View File

@ -1,20 +1,20 @@
return function(x, y, world)
local distance = math.sqrt(x * x + y * y)
if distance > 128 then
local angle = 180 + math.deg(math.atan2(x, y))
local offset = distance
local offset2 = distance
if angle ~= 0 then
offset2 = offset - angle / 3.75
offset = offset + angle / 3.75
end
--if angle ~= 0 then offset = offset + angle /1.33333333 end
if offset % 96 < 64 then
return offset2 % 96 >= 64
end
end
return true
end
return function(x, y, world)
local distance = math.sqrt(x * x + y * y)
if distance > 128 then
local angle = 180 + math.deg(math.atan2(x, y))
local offset = distance
local offset2 = distance
if angle ~= 0 then
offset2 = offset - angle / 3.75
offset = offset + angle / 3.75
end
--if angle ~= 0 then offset = offset + angle /1.33333333 end
if offset % 96 < 64 then
return offset2 % 96 >= 64
end
end
return true
end

View File

@ -1,23 +1,23 @@
return function(x, y, world)
local distance = math.sqrt(x * x + y * y)
if distance > 128 then
local angle = (180 + math.deg(math.atan2(x, y))) * 3
local offset = distance * 0.75
if angle ~= 0 then
offset = offset + angle / 3.75
end
--if angle ~= 0 then offset = offset + angle /1.33333333 end
if offset % 96 < 48 then
local offset2 = distance * 0.125
if angle ~= 0 then
offset2 = offset2 - angle / 3.75
end
return offset2 % 96 >= 80
end
end
return true
end
return function(x, y, world)
local distance = math.sqrt(x * x + y * y)
if distance > 128 then
local angle = (180 + math.deg(math.atan2(x, y))) * 3
local offset = distance * 0.75
if angle ~= 0 then
offset = offset + angle / 3.75
end
--if angle ~= 0 then offset = offset + angle /1.33333333 end
if offset % 96 < 48 then
local offset2 = distance * 0.125
if angle ~= 0 then
offset2 = offset2 - angle / 3.75
end
return offset2 % 96 >= 80
end
end
return true
end

View File

@ -1,21 +1,21 @@
-- Author: flowild
local arm_width = 96
local function is_on_spiral(x, y, distance, angle_offset)
local angle = angle_offset + math.deg(math.atan2(x, y))
local offset = distance
if angle ~= 0 then
offset = offset + angle / 3.75 * 2
end
return offset % 96 * 2 >= 48 * 2
end
return function(x, y, world)
local pseudo_x = x / (arm_width / 48)
local pseudo_y = y / (arm_width / 48)
local distance = math.sqrt(pseudo_x * pseudo_x + pseudo_y * pseudo_y)
return not (distance > 100 and not is_on_spiral(x, y, distance, 0))
end
-- Author: flowild
local arm_width = 96
local function is_on_spiral(x, y, distance, angle_offset)
local angle = angle_offset + math.deg(math.atan2(x, y))
local offset = distance
if angle ~= 0 then
offset = offset + angle / 3.75 * 2
end
return offset % 96 * 2 >= 48 * 2
end
return function(x, y, world)
local pseudo_x = x / (arm_width / 48)
local pseudo_y = y / (arm_width / 48)
local distance = math.sqrt(pseudo_x * pseudo_x + pseudo_y * pseudo_y)
return not (distance > 100 and not is_on_spiral(x, y, distance, 0))
end

View File

@ -1,3 +1,3 @@
return function(x, y, world)
return not (x > 180 or x < -180 or y > 80)
end
return function(x, y, world)
return not (x > 180 or x < -180 or y > 80)
end

File diff suppressed because it is too large Load Diff

View File

@ -1,106 +1,106 @@
--from https://github.com/thenumbernine/lua-simplexnoise/blob/master/2d.lua
--Mostly as a test, does not give same results as perlin but is designed to give patterns all the same
local Simplex = {}
-- 2D simplex noise
local grad3 = {
{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
}
local p = {151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
local perm = {}
for i=0,511 do
perm[i+1] = p[bit32.band(i, 255) + 1]
end
local function dot(g, ...)
local v = {...}
local sum = 0
for i=1,#v do
sum = sum + v[i] * g[i]
end
return sum
end
local F2 = 0.5*(math.sqrt(3.0)-1.0)
local G2 = (3.0-math.sqrt(3.0))/6.0
function Simplex.d2(xin, yin,seed)
xin = xin + seed
yin = yin + seed
local n0, n1, n2 -- Noise contributions from the three corners
-- Skew the input space to determine which simplex cell we're in
local s = (xin+yin)*F2; -- Hairy factor for 2D
local i = math.floor(xin+s)
local j = math.floor(yin+s)
local t = (i+j)*G2
local X0 = i-t -- Unskew the cell origin back to (x,y) space
local Y0 = j-t
local x0 = xin-X0 -- The x,y distances from the cell origin
local y0 = yin-Y0
-- For the 2D case, the simplex shape is an equilateral triangle.
-- Determine which simplex we are in.
local i1, j1 -- Offsets for second (middle) corner of simplex in (i,j) coords
if x0 > y0 then
i1 = 1
j1 = 0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
else
i1 = 0
j1 = 1
end-- upper triangle, YX order: (0,0)->(0,1)->(1,1)
-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
-- c = (3-sqrt(3))/6
local x1 = x0 - i1 + G2 -- Offsets for middle corner in (x,y) unskewed coords
local y1 = y0 - j1 + G2
local x2 = x0 - 1 + 2 * G2 -- Offsets for last corner in (x,y) unskewed coords
local y2 = y0 - 1 + 2 * G2
-- Work out the hashed gradient indices of the three simplex corners
local ii = bit32.band(i, 255)
local jj = bit32.band(j, 255)
local gi0 = perm[ii + perm[jj+1]+1] % 12
local gi1 = perm[ii + i1 + perm[jj + j1+1]+1] % 12
local gi2 = perm[ii + 1 + perm[jj + 1+1]+1] % 12
-- Calculate the contribution from the three corners
local t0 = 0.5 - x0 * x0 - y0 * y0
if t0 < 0 then
n0 = 0.0
else
t0 = t0 * t0
n0 = t0 * t0 * dot(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
end
local t1 = 0.5 - x1 * x1 - y1 * y1
if t1 < 0 then
n1 = 0.0
else
t1 = t1 * t1
n1 = t1 * t1 * dot(grad3[gi1+1], x1, y1)
end
local t2 = 0.5 - x2 * x2 - y2 * y2
if t2 < 0 then
n2 = 0.0
else
t2 = t2 * t2
n2 = t2 * t2 * dot(grad3[gi2+1], x2, y2)
end
-- Add contributions from each corner to get the final noise value.
-- The result is scaled to return values in the interval [-1,1].
return 70.0 * (n0 + n1 + n2)
end
return Simplex
--from https://github.com/thenumbernine/lua-simplexnoise/blob/master/2d.lua
--Mostly as a test, does not give same results as perlin but is designed to give patterns all the same
local Simplex = {}
-- 2D simplex noise
local grad3 = {
{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
}
local p = {151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
local perm = {}
for i=0,511 do
perm[i+1] = p[bit32.band(i, 255) + 1]
end
local function dot(g, ...)
local v = {...}
local sum = 0
for i=1,#v do
sum = sum + v[i] * g[i]
end
return sum
end
local F2 = 0.5*(math.sqrt(3.0)-1.0)
local G2 = (3.0-math.sqrt(3.0))/6.0
function Simplex.d2(xin, yin,seed)
xin = xin + seed
yin = yin + seed
local n0, n1, n2 -- Noise contributions from the three corners
-- Skew the input space to determine which simplex cell we're in
local s = (xin+yin)*F2; -- Hairy factor for 2D
local i = math.floor(xin+s)
local j = math.floor(yin+s)
local t = (i+j)*G2
local X0 = i-t -- Unskew the cell origin back to (x,y) space
local Y0 = j-t
local x0 = xin-X0 -- The x,y distances from the cell origin
local y0 = yin-Y0
-- For the 2D case, the simplex shape is an equilateral triangle.
-- Determine which simplex we are in.
local i1, j1 -- Offsets for second (middle) corner of simplex in (i,j) coords
if x0 > y0 then
i1 = 1
j1 = 0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
else
i1 = 0
j1 = 1
end-- upper triangle, YX order: (0,0)->(0,1)->(1,1)
-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
-- c = (3-sqrt(3))/6
local x1 = x0 - i1 + G2 -- Offsets for middle corner in (x,y) unskewed coords
local y1 = y0 - j1 + G2
local x2 = x0 - 1 + 2 * G2 -- Offsets for last corner in (x,y) unskewed coords
local y2 = y0 - 1 + 2 * G2
-- Work out the hashed gradient indices of the three simplex corners
local ii = bit32.band(i, 255)
local jj = bit32.band(j, 255)
local gi0 = perm[ii + perm[jj+1]+1] % 12
local gi1 = perm[ii + i1 + perm[jj + j1+1]+1] % 12
local gi2 = perm[ii + 1 + perm[jj + 1+1]+1] % 12
-- Calculate the contribution from the three corners
local t0 = 0.5 - x0 * x0 - y0 * y0
if t0 < 0 then
n0 = 0.0
else
t0 = t0 * t0
n0 = t0 * t0 * dot(grad3[gi0+1], x0, y0) -- (x,y) of grad3 used for 2D gradient
end
local t1 = 0.5 - x1 * x1 - y1 * y1
if t1 < 0 then
n1 = 0.0
else
t1 = t1 * t1
n1 = t1 * t1 * dot(grad3[gi1+1], x1, y1)
end
local t2 = 0.5 - x2 * x2 - y2 * y2
if t2 < 0 then
n2 = 0.0
else
t2 = t2 * t2
n2 = t2 * t2 * dot(grad3[gi2+1], x2, y2)
end
-- Add contributions from each corner to get the final noise value.
-- The result is scaled to return values in the interval [-1,1].
return 70.0 * (n0 + n1 + n2)
end
return Simplex

View File

@ -1,178 +1,178 @@
local perlin = require 'map_gen.shared.perlin_noise'
local simplex = require 'map_gen.shared.simplex_noise'
local tree_to_place = {'dry-tree', 'dry-hairy-tree', 'tree-06', 'tree-06', 'tree-01', 'tree-02', 'tree-03'}
function run_terrain_module(event)
if not global.terrain_seed_A then
global.terrain_seed_A = math.random(10, 10000)
end
if not global.terrain_seed_B then
global.terrain_seed_B = math.random(10, 10000)
end
local area = event.area
local surface = event.surface
local tiles = {}
local tileswater = {}
local entities = surface.find_entities(area)
for _, entity in pairs(entities) do
--if entity.type == "simple-entity" or entity.type == "resource" or entity.type == "tree" then
if entity.type == 'simple-entity' or entity.type == 'tree' then
--end
entity.destroy()
elseif (run_ores_module ~= nil and entity.type == 'resource') then
entity.destroy()
end
end
local top_left = area.left_top --make a more direct reference
--do it only per chunk, cause cheaper than every square, and who care anyway.
--local distance_bonus = 200 + math.sqrt(top_left.x*top_left.x + top_left.y*top_left.y) * 0.2
--for x = 0, 31, 1 do
-- for y = 0, 31, 1 do
--game.print(top_left.x .."-" ..top_left.y .. " to " .. area.right_bottom.x .. "-" .. area.right_bottom.y)
for x = top_left.x - 1, top_left.x + 32 do
for y = top_left.y - 1, top_left.y + 32 do
--local pos_x = top_left.x + x
--local pos_y = top_left.y + y
local tile = surface.get_tile(x, y)
if tile.name ~= 'out-of-map' then
local tile_to_insert = 'grass-3'
local wiggle = 50 + perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 71) * 60
local terrain_A = perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 19) * wiggle --For determining where water is
local terrain_sqr = terrain_A * terrain_A --we can use this again to mess with other layers as well
local terrain_D = 10 + perlin.noise((x * 0.001), (y * 0.001), global.terrain_seed_A + 5) * wiggle --terrain layer
--local wiggle = 50 + Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 71) * 60
--local terrain_A = Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 19) * wiggle --For determining where water is
--local terrain_sqr = terrain_A * terrain_A --we can use this again to mess with other layers as well
--local terrain_D = 10 + Simplex.d2((x*0.001),(y*0.001),global.terrain_seed_A + 5) * wiggle --terrain layer
if terrain_sqr < 50 then --Main water areas
--local deep = (terrain_sqr < 20) and true or false
terrain_A = perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_A + 31) * 90 + (wiggle * -0.2) --we only gen this when we consider placing water
--terrain_A = Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_A + 31) * 90 + (wiggle * -0.2) --we only gen this when we consider placing water
if terrain_A * terrain_A > 40 then --creates random bridges over the water by overlapping with another noise layer
--table.insert(tileswater, {name = "water", position = {x,y}})
--table.insert(tileswater, {name = "water", position = {x+1,y}})
--table.insert(tileswater, {name = "water", position = {x,y+1}})
--table.insert(tileswater, {name = "water", position = {x+1,y+1}})
tile_to_insert = 'water'
else
if terrain_D >= 20 then
tile_to_insert = 'sand-1'
end
end
elseif terrain_sqr > 70 then
wiggle = 100 + perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_B + 41) * 60
local terrain_C = perlin.noise((x * 0.02), (y * 0.02), global.terrain_seed_A + 13) * wiggle --tree layer
--wiggle = 100 + Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_B + 41) * 60
--local terrain_C = Simplex.d2((x*0.02),(y*0.02),global.terrain_seed_A + 13) * wiggle --tree layer
--if surface.can_place_entity {name="stone", position={x,y}} then
-- surface.create_entity {name="stone", position={x,y}, amount=math.floor(terrain_sqr)}
--end
if run_ores_module ~= nil then
run_ores_module_setup()
if x > top_left.x - 1 and x < top_left.x + 32 and y > top_left.y - 1 and y < top_left.y + 32 then
run_ores_module_tile(surface, x, y)
end
end
--if terrain_B > 35 then --we place ores
-- local a = 5
--
-- if terrain_B < 76 then a = math.floor(terrain_B*0.75 + terrain_C*0.5) % 4 + 1 end --if its not super high we place normal ores
--
-- local res_amount = distance_bonus + terrain_sqr * 0.1
-- res_amount = math.floor(res_amount * random_dense[a])
--
-- if surface.can_place_entity {name=random_ores[a], position={pos_x,pos_y}} then
-- surface.create_entity {name=random_ores[a], position={pos_x,pos_y}, amount=res_amount}
-- end
--end
--wiggle = 100 + perlin.noise((pos_x*0.02),(pos_y*0.02),global.terrain_seed_B + 71) * 60
if terrain_D < 20 then
if terrain_C < 4 then --we set grass-1 around near forest areas
tile_to_insert = 'grass-1'
if terrain_C < -20 and math.random(1, 3) == 1 then --dense trees
local treenum = math.random(3, 7)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
else
if terrain_C < 0 and math.random(1, 7) == 1 then --less dense trees
local treenum = math.random(3, 5)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
end
end
end
else
if terrain_D < 30 then
tile_to_insert = 'sand-1'
if terrain_C < -20 and math.random(1, 7) == 1 then --dense trees
local treenum = math.random(1, 3)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
elseif terrain_C < 0 and math.random(1, 13) == 1 then --less dense trees
local treenum = math.random(1, 2)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
end
else
--if terrain_C > 40 and math.random(1,200) == 1 and surface.can_place_entity {name="crude-oil", position={pos_x,pos_y}} then
-- surface.create_entity {name="crude-oil", position={pos_x,pos_y}, amount = math.random(20000,60000) +distance_bonus* 2000 }
--end
tile_to_insert = 'sand-3'
end
end
if
math.floor(terrain_D) % 5 == 1 and math.random(1, 70) == 1 and
surface.can_place_entity {name = 'rock-big', position = {x, y}}
then
surface.create_entity {name = 'rock-big', position = {x, y}}
end
else
if terrain_D >= 20 then
if terrain_D < 30 then
tile_to_insert = 'sand-1'
else
tile_to_insert = 'sand-3'
end
end
end
--if tile_to_insert == "water" then
--table.insert(tileswater, {name = tile_to_insert, position = {x,y}})
--else
table.insert(tiles, {name = tile_to_insert, position = {x, y}})
--end
end
end
end
--game.print("break end")
--game.print(lowest .. " to " .. highest)
surface.set_tiles(tiles, true)
--surface.set_tiles(tileswater,true)
end
local perlin = require 'map_gen.shared.perlin_noise'
local simplex = require 'map_gen.shared.simplex_noise'
local tree_to_place = {'dry-tree', 'dry-hairy-tree', 'tree-06', 'tree-06', 'tree-01', 'tree-02', 'tree-03'}
function run_terrain_module(event)
if not global.terrain_seed_A then
global.terrain_seed_A = math.random(10, 10000)
end
if not global.terrain_seed_B then
global.terrain_seed_B = math.random(10, 10000)
end
local area = event.area
local surface = event.surface
local tiles = {}
local tileswater = {}
local entities = surface.find_entities(area)
for _, entity in pairs(entities) do
--if entity.type == "simple-entity" or entity.type == "resource" or entity.type == "tree" then
if entity.type == 'simple-entity' or entity.type == 'tree' then
--end
entity.destroy()
elseif (run_ores_module ~= nil and entity.type == 'resource') then
entity.destroy()
end
end
local top_left = area.left_top --make a more direct reference
--do it only per chunk, cause cheaper than every square, and who care anyway.
--local distance_bonus = 200 + math.sqrt(top_left.x*top_left.x + top_left.y*top_left.y) * 0.2
--for x = 0, 31, 1 do
-- for y = 0, 31, 1 do
--game.print(top_left.x .."-" ..top_left.y .. " to " .. area.right_bottom.x .. "-" .. area.right_bottom.y)
for x = top_left.x - 1, top_left.x + 32 do
for y = top_left.y - 1, top_left.y + 32 do
--local pos_x = top_left.x + x
--local pos_y = top_left.y + y
local tile = surface.get_tile(x, y)
if tile.name ~= 'out-of-map' then
local tile_to_insert = 'grass-3'
local wiggle = 50 + perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 71) * 60
local terrain_A = perlin.noise((x * 0.005), (y * 0.005), global.terrain_seed_A + 19) * wiggle --For determining where water is
local terrain_sqr = terrain_A * terrain_A --we can use this again to mess with other layers as well
local terrain_D = 10 + perlin.noise((x * 0.001), (y * 0.001), global.terrain_seed_A + 5) * wiggle --terrain layer
--local wiggle = 50 + Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 71) * 60
--local terrain_A = Simplex.d2((x*0.005),(y*0.005),global.terrain_seed_A + 19) * wiggle --For determining where water is
--local terrain_sqr = terrain_A * terrain_A --we can use this again to mess with other layers as well
--local terrain_D = 10 + Simplex.d2((x*0.001),(y*0.001),global.terrain_seed_A + 5) * wiggle --terrain layer
if terrain_sqr < 50 then --Main water areas
--local deep = (terrain_sqr < 20) and true or false
terrain_A = perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_A + 31) * 90 + (wiggle * -0.2) --we only gen this when we consider placing water
--terrain_A = Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_A + 31) * 90 + (wiggle * -0.2) --we only gen this when we consider placing water
if terrain_A * terrain_A > 40 then --creates random bridges over the water by overlapping with another noise layer
--table.insert(tileswater, {name = "water", position = {x,y}})
--table.insert(tileswater, {name = "water", position = {x+1,y}})
--table.insert(tileswater, {name = "water", position = {x,y+1}})
--table.insert(tileswater, {name = "water", position = {x+1,y+1}})
tile_to_insert = 'water'
else
if terrain_D >= 20 then
tile_to_insert = 'sand-1'
end
end
elseif terrain_sqr > 70 then
wiggle = 100 + perlin.noise((x * 0.01), (y * 0.01), global.terrain_seed_B + 41) * 60
local terrain_C = perlin.noise((x * 0.02), (y * 0.02), global.terrain_seed_A + 13) * wiggle --tree layer
--wiggle = 100 + Simplex.d2((x*0.01),(y*0.01),global.terrain_seed_B + 41) * 60
--local terrain_C = Simplex.d2((x*0.02),(y*0.02),global.terrain_seed_A + 13) * wiggle --tree layer
--if surface.can_place_entity {name="stone", position={x,y}} then
-- surface.create_entity {name="stone", position={x,y}, amount=math.floor(terrain_sqr)}
--end
if run_ores_module ~= nil then
run_ores_module_setup()
if x > top_left.x - 1 and x < top_left.x + 32 and y > top_left.y - 1 and y < top_left.y + 32 then
run_ores_module_tile(surface, x, y)
end
end
--if terrain_B > 35 then --we place ores
-- local a = 5
--
-- if terrain_B < 76 then a = math.floor(terrain_B*0.75 + terrain_C*0.5) % 4 + 1 end --if its not super high we place normal ores
--
-- local res_amount = distance_bonus + terrain_sqr * 0.1
-- res_amount = math.floor(res_amount * random_dense[a])
--
-- if surface.can_place_entity {name=random_ores[a], position={pos_x,pos_y}} then
-- surface.create_entity {name=random_ores[a], position={pos_x,pos_y}, amount=res_amount}
-- end
--end
--wiggle = 100 + perlin.noise((pos_x*0.02),(pos_y*0.02),global.terrain_seed_B + 71) * 60
if terrain_D < 20 then
if terrain_C < 4 then --we set grass-1 around near forest areas
tile_to_insert = 'grass-1'
if terrain_C < -20 and math.random(1, 3) == 1 then --dense trees
local treenum = math.random(3, 7)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
else
if terrain_C < 0 and math.random(1, 7) == 1 then --less dense trees
local treenum = math.random(3, 5)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
end
end
end
else
if terrain_D < 30 then
tile_to_insert = 'sand-1'
if terrain_C < -20 and math.random(1, 7) == 1 then --dense trees
local treenum = math.random(1, 3)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
elseif terrain_C < 0 and math.random(1, 13) == 1 then --less dense trees
local treenum = math.random(1, 2)
if surface.can_place_entity {name = tree_to_place[treenum], position = {x, y}} then
surface.create_entity {name = tree_to_place[treenum], position = {x, y}}
end
end
else
--if terrain_C > 40 and math.random(1,200) == 1 and surface.can_place_entity {name="crude-oil", position={pos_x,pos_y}} then
-- surface.create_entity {name="crude-oil", position={pos_x,pos_y}, amount = math.random(20000,60000) +distance_bonus* 2000 }
--end
tile_to_insert = 'sand-3'
end
end
if
math.floor(terrain_D) % 5 == 1 and math.random(1, 70) == 1 and
surface.can_place_entity {name = 'rock-big', position = {x, y}}
then
surface.create_entity {name = 'rock-big', position = {x, y}}
end
else
if terrain_D >= 20 then
if terrain_D < 30 then
tile_to_insert = 'sand-1'
else
tile_to_insert = 'sand-3'
end
end
end
--if tile_to_insert == "water" then
--table.insert(tileswater, {name = tile_to_insert, position = {x,y}})
--else
table.insert(tiles, {name = tile_to_insert, position = {x, y}})
--end
end
end
end
--game.print("break end")
--game.print(lowest .. " to " .. highest)
surface.set_tiles(tiles, true)
--surface.set_tiles(tileswater,true)
end

View File

@ -1,157 +1,157 @@
local Module = {}
local Game = require 'utils.game'
local prefix = '## - '
Module.distance = function(pos1, pos2)
local dx = pos2.x - pos1.x
local dy = pos2.y - pos1.y
return math.sqrt(dx * dx + dy * dy)
end
Module.print_except = function(msg, player)
for _, p in pairs(game.players) do
if p.connected and p ~= player then
p.print(msg)
end
end
end
-- Takes a LuaPlayer or string as source
Module.print_admins = function(msg, source)
local source_name
local chat_color
if source then
if type(source) == 'string' then
source_name = source
chat_colot = game.players[source].chat_color
else
source_name = source.name
chat_color = source.chat_color
end
else
source_name = "Server"
chat_color = {r=255, g=255, b=255}
end
for _, p in pairs(game.connected_players) do
if p.admin then
p.print(string.format('%s(ADMIN) %s: %s', prefix, source_name, msg), chat_color)
end
end
end
Module.get_actor = function()
if game.player then
return game.player.name
end
return '<server>'
end
Module.cast_bool = function(var)
if var then
return true
else
return false
end
end
Module.find_entities_by_last_user =
function(player, surface, filters)
if type(player) == 'string' or not player then
error(
"bad argument #1 to '" ..
debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')',
1
)
return
end
if type(surface) ~= 'table' and type(surface) ~= 'number' then
error(
"bad argument #2 to '" ..
debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')',
1
)
return
end
local entities = {}
local surface = surface
local player = player
local filters = filters or {}
if type(surface) == 'number' then
surface = game.surfaces[surface]
end
if type(player) == 'number' then
player = Game.get_player_by_index(player)
end
filters.force = player.force.name
for _, e in pairs(surface.find_entities_filtered(filters)) do
if e.last_user == player then
table.insert(entities, e)
end
end
return entities
end
Module.ternary = function(c, t, f)
if c then
return t
else
return f
end
end
local minutes_to_ticks = 60 * 60
local hours_to_ticks = 60 * 60 * 60
local ticks_to_minutes = 1 / minutes_to_ticks
local ticks_to_hours = 1 / hours_to_ticks
Module.format_time = function(ticks)
local result = {}
local hours = math.floor(ticks * ticks_to_hours)
if hours > 0 then
ticks = ticks - hours * hours_to_ticks
table.insert(result, hours)
if hours == 1 then
table.insert(result, 'hour')
else
table.insert(result, 'hours')
end
end
local minutes = math.floor(ticks * ticks_to_minutes)
table.insert(result, minutes)
if minutes == 1 then
table.insert(result, 'minute')
else
table.insert(result, 'minutes')
end
return table.concat(result, ' ')
end
Module.cant_run = function(name)
Game.player_print("Can't run command (" .. name .. ') - insufficient permission.')
end
Module.log_command = function(user, command, parameters)
local name
-- We can use a LuaPlayer or a string (ex. "Server").
if type(user) == 'string' then
name = user
else
name = user.name
end
local action = table.concat {'[Admin-Command] ', name, ' used: ', command}
if parameters then
action = table.concat {'[Admin-Command] ', name, ' used: ', command, ' ', parameters}
end
log(action)
end
Module.comma_value = function(n) -- credit http://richard.warburton.it
local left,num,right = string.match(n, '^([^%d]*%d)(%d*)(.-)$')
return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right
end
return Module
local Module = {}
local Game = require 'utils.game'
local prefix = '## - '
Module.distance = function(pos1, pos2)
local dx = pos2.x - pos1.x
local dy = pos2.y - pos1.y
return math.sqrt(dx * dx + dy * dy)
end
Module.print_except = function(msg, player)
for _, p in pairs(game.players) do
if p.connected and p ~= player then
p.print(msg)
end
end
end
-- Takes a LuaPlayer or string as source
Module.print_admins = function(msg, source)
local source_name
local chat_color
if source then
if type(source) == 'string' then
source_name = source
chat_colot = game.players[source].chat_color
else
source_name = source.name
chat_color = source.chat_color
end
else
source_name = "Server"
chat_color = {r=255, g=255, b=255}
end
for _, p in pairs(game.connected_players) do
if p.admin then
p.print(string.format('%s(ADMIN) %s: %s', prefix, source_name, msg), chat_color)
end
end
end
Module.get_actor = function()
if game.player then
return game.player.name
end
return '<server>'
end
Module.cast_bool = function(var)
if var then
return true
else
return false
end
end
Module.find_entities_by_last_user =
function(player, surface, filters)
if type(player) == 'string' or not player then
error(
"bad argument #1 to '" ..
debug.getinfo(1, 'n').name .. "' (number or LuaPlayer expected, got " .. type(player) .. ')',
1
)
return
end
if type(surface) ~= 'table' and type(surface) ~= 'number' then
error(
"bad argument #2 to '" ..
debug.getinfo(1, 'n').name .. "' (number or LuaSurface expected, got " .. type(surface) .. ')',
1
)
return
end
local entities = {}
local surface = surface
local player = player
local filters = filters or {}
if type(surface) == 'number' then
surface = game.surfaces[surface]
end
if type(player) == 'number' then
player = Game.get_player_by_index(player)
end
filters.force = player.force.name
for _, e in pairs(surface.find_entities_filtered(filters)) do
if e.last_user == player then
table.insert(entities, e)
end
end
return entities
end
Module.ternary = function(c, t, f)
if c then
return t
else
return f
end
end
local minutes_to_ticks = 60 * 60
local hours_to_ticks = 60 * 60 * 60
local ticks_to_minutes = 1 / minutes_to_ticks
local ticks_to_hours = 1 / hours_to_ticks
Module.format_time = function(ticks)
local result = {}
local hours = math.floor(ticks * ticks_to_hours)
if hours > 0 then
ticks = ticks - hours * hours_to_ticks
table.insert(result, hours)
if hours == 1 then
table.insert(result, 'hour')
else
table.insert(result, 'hours')
end
end
local minutes = math.floor(ticks * ticks_to_minutes)
table.insert(result, minutes)
if minutes == 1 then
table.insert(result, 'minute')
else
table.insert(result, 'minutes')
end
return table.concat(result, ' ')
end
Module.cant_run = function(name)
Game.player_print("Can't run command (" .. name .. ') - insufficient permission.')
end
Module.log_command = function(user, command, parameters)
local name
-- We can use a LuaPlayer or a string (ex. "Server").
if type(user) == 'string' then
name = user
else
name = user.name
end
local action = table.concat {'[Admin-Command] ', name, ' used: ', command}
if parameters then
action = table.concat {'[Admin-Command] ', name, ' used: ', command, ' ', parameters}
end
log(action)
end
Module.comma_value = function(n) -- credit http://richard.warburton.it
local left,num,right = string.match(n, '^([^%d]*%d)(%d*)(.-)$')
return left .. (num:reverse():gsub('(%d%d%d)', '%1,'):reverse()) .. right
end
return Module