mirror of
https://github.com/jvmguy/JvmguyScenario.git
synced 2024-11-21 17:16:46 +02:00
Reworked enemy clearing. Somewhat like Oarc's method, but a little different.
This commit is contained in:
parent
281b708012
commit
95122a8a5f
55
config.lua
55
config.lua
@ -609,20 +609,13 @@ ENABLE_SPAWN_FORCE_GRASS = true
|
||||
-- Safe Spawn Area Options
|
||||
---------------------------------------
|
||||
|
||||
-- Safe area has no aliens
|
||||
-- +/- this in x and y direction
|
||||
SAFE_AREA_TILE_DIST = CHUNK_SIZE*8
|
||||
-- These settings are deprecated,
|
||||
-- replaced by scenario.config.safe_area
|
||||
-- but still appear in a few places.
|
||||
|
||||
-- Safe area around bunker entrance that has no aliens
|
||||
SAFE_AREA_BUNKER_ENTRANCE_TILE_DIST = CHUNK_SIZE * 2
|
||||
|
||||
-- Warning area has reduced aliens
|
||||
-- +/- this in x and y direction
|
||||
WARNING_AREA_TILE_DIST = CHUNK_SIZE*10
|
||||
|
||||
-- 1 : X (spawners alive : spawners destroyed) in this area
|
||||
WARN_AREA_REDUCTION_RATIO = 15
|
||||
|
||||
-- Create a circle of land area for the spawn
|
||||
-- deprecated
|
||||
ENFORCE_LAND_AREA_TILE_DIST = 84
|
||||
@ -725,6 +718,29 @@ AUTOFILL_FLAMETHROWER_AMMO_QUANTITY=20
|
||||
global.oarcDebugEnabled = false
|
||||
global.jvmguyDebugEnabled = false
|
||||
|
||||
scenario.config.modified_enemy_spawning = true;
|
||||
|
||||
scenario.config.safe_area =
|
||||
{
|
||||
-- Safe area has no aliens
|
||||
-- This is the radius in tiles of safe area.
|
||||
safe_radius = CHUNK_SIZE*6,
|
||||
|
||||
-- Warning area has significantly reduced aliens
|
||||
-- This is the radius in tiles of warning area.
|
||||
warn_radius = CHUNK_SIZE*16,
|
||||
|
||||
-- 1 : X (spawners alive : spawners destroyed) in this area
|
||||
warn_reduction_fraction = 0.05,
|
||||
|
||||
-- Danger area has slightly reduce aliens
|
||||
-- This is the radius in tiles of danger area.
|
||||
danger_radius = CHUNK_SIZE*32,
|
||||
|
||||
-- 1 : X (spawners alive : spawners destroyed) in this area
|
||||
danger_reduction_fraction = 0.4,
|
||||
}
|
||||
|
||||
|
||||
scenario.config.fermatSpiralSpawns = {
|
||||
-- this mostly inherits the separateSpawns config, but has a few minor differences
|
||||
@ -758,6 +774,7 @@ scenario.config.fermatSpiralSpawns = {
|
||||
|
||||
recipesEnabled = scenario.config.recipesEnabled,
|
||||
recipesDisabled = scenario.config.recipesDisabled,
|
||||
safe_area = scenario.config.safe_area,
|
||||
}
|
||||
|
||||
scenario.config.bunkerSpawns = {
|
||||
@ -800,6 +817,7 @@ scenario.config.bunkerSpawns = {
|
||||
|
||||
recipesEnabled = scenario.config.recipesEnabled,
|
||||
recipesDisabled = scenario.config.recipesDisabled,
|
||||
safe_area = scenario.config.safe_area,
|
||||
}
|
||||
|
||||
scenario.config.riverworld = {
|
||||
@ -820,9 +838,9 @@ scenario.config.riverworld = {
|
||||
rail2 = -3*640-32, -- generate a north-south railway starting here
|
||||
freespace = 3*640 + 32, -- no voids after this
|
||||
|
||||
land = 84,
|
||||
land = 76,
|
||||
trees = 3, -- included in the land
|
||||
moat = 0, -- additional to land
|
||||
moat = 8, -- additional to land
|
||||
size = 84, -- should be land + moat
|
||||
|
||||
-- this is a vertical moat, not the usual one around the spawn.
|
||||
@ -835,15 +853,8 @@ scenario.config.riverworld = {
|
||||
-- you might get night vision at the start, but you have to decide whether it's worth using it.
|
||||
-- freezeTime = 0.5, -- see https://wiki.factorio.com/Game-day
|
||||
-- 0 is day. 0.5 is night. 0.35 is twilight.
|
||||
recipesEnabled = {
|
||||
-- "loader",
|
||||
-- "fast-loader",
|
||||
-- "express-loader",
|
||||
},
|
||||
-- surfaces = {
|
||||
-- aboveground = {
|
||||
-- name = GAME_SURFACE_NAME,
|
||||
-- },
|
||||
-- }
|
||||
recipesEnabled = scenario.config.recipesEnabled,
|
||||
recipesDisabled = scenario.config.recipesDisabled,
|
||||
safe_area = scenario.config.safe_area,
|
||||
}
|
||||
|
||||
|
27
control.lua
27
control.lua
@ -56,12 +56,12 @@ require("lib/frontier_silo")
|
||||
|
||||
toxicJungle = require("lib/ToxicJungle")
|
||||
|
||||
spawnGenerator = require("lib/FermatSpiralSpawns");
|
||||
-- spawnGenerator = require("RiverworldSpawns");
|
||||
--spawnGenerator = require("BunkerSpawns");
|
||||
-- spawnGenerator = require("lib/FermatSpiralSpawns");
|
||||
spawnGenerator = require("lib/RiverworldSpawns");
|
||||
--spawnGenerator = require("lib/BunkerSpawns");
|
||||
|
||||
local terrainGenerator = nil;
|
||||
-- terrainGenerator = require("GeometricTerrain");
|
||||
-- terrainGenerator = require("lib/GeometricTerrain");
|
||||
|
||||
sharedSpawns = require("lib/shared_spawns");
|
||||
|
||||
@ -314,7 +314,6 @@ function jvm.on_research_finished(event)
|
||||
if FRONTIER_ROCKET_SILO_MODE then
|
||||
RemoveRocketSiloRecipe(event)
|
||||
end
|
||||
|
||||
-- local config = spawnGenerator.GetConfig()
|
||||
-- if config.recipesEnabled then
|
||||
-- for kk,vv in pairs(config.recipesEnabled) do
|
||||
@ -325,9 +324,23 @@ function jvm.on_research_finished(event)
|
||||
-- Example of how to remove a particular recipe:
|
||||
-- RemoveRecipe(event, "beacon")
|
||||
end
|
||||
|
||||
Event.register(defines.events.on_research_finished, jvm.on_research_finished)
|
||||
|
||||
function jvm.on_entity_spawned(event)
|
||||
if (scenario.config.modified_enemy_spawning) then
|
||||
-- ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
end
|
||||
end
|
||||
Event.register(defines.events.on_entity_spawned, jvm.on_entity_spawned)
|
||||
|
||||
|
||||
function jvm.on_biter_base_built(event)
|
||||
if (scenario.config.modified_enemy_spawning) then
|
||||
-- ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
end
|
||||
end
|
||||
Event.register(defines.events.on_biter_base_built, jvm.on_biter_base_built)
|
||||
|
||||
|
||||
----------------------------------------
|
||||
-- BPS Specific Event
|
||||
@ -338,7 +351,7 @@ Event.register(defines.events.on_research_finished, jvm.on_research_finished)
|
||||
-- debug code from Mylon to detect possible causes for desync
|
||||
--Time for the debug code. If any (not global.) globals are written to at this point, an error will be thrown.
|
||||
--eg, x = 2 will throw an error because it's not global.x or local x
|
||||
if false then
|
||||
if true then
|
||||
setmetatable(_G, {
|
||||
__newindex = function(_, n, v)
|
||||
logInfo("", "Attempt to write to undeclared var " .. n)
|
||||
|
4
description.json
Normal file
4
description.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"order": "a",
|
||||
"multiplayer-compatible": true
|
||||
}
|
@ -233,7 +233,7 @@ function M.ChunkGenerated(event)
|
||||
|
||||
-- Common spawn generation code.
|
||||
if spawnPos ~= nil then
|
||||
DestroyEnemies(chunkArea, surface, spawnPos, config.craterSize);
|
||||
ClearNearbyEnemies(chunkArea, surface, spawnPos);
|
||||
if config.crater then
|
||||
MakeSpawnCrater(chunkArea, surface, spawnPos);
|
||||
end
|
||||
|
@ -344,17 +344,9 @@ function M.GenerateRailsAndWalls(surface, chunkArea, spawnPos)
|
||||
GenerateRails( surface, chunkArea, scenario.config.riverworld.rail2, railsRect2)
|
||||
end
|
||||
|
||||
function M.ClearEnemiesInRadius(surface, position, safeDist, chunkArea)
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = chunkArea, force = "enemy"}) do
|
||||
if entity and entity.valid and DistanceFromPoint(position, entity.position) < safeDist then
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.CreateSpawn(surface, spawnPos, chunkArea)
|
||||
local config = M.GetConfig()
|
||||
M.ClearEnemiesInRadius(surface, spawnPos, SAFE_AREA_TILE_DIST, chunkArea)
|
||||
ClearNearbyEnemies(surface, chunkArea, spawnPos)
|
||||
CreateCropOctagon(surface, spawnPos, chunkArea, config.land, config.trees, config.moat)
|
||||
if config.concrete then
|
||||
PaveWithConcrete( surface, chunkArea, spawnPos, config.land);
|
||||
@ -398,7 +390,7 @@ function M.ChunkGenerated(event)
|
||||
|
||||
-- Common spawn generation code.
|
||||
if spawnPos ~= nil then
|
||||
DestroyEnemies(chunkArea, surface, spawnPos, SAFE_AREA_TILE_DIST);
|
||||
ClearNearbyEnemies(surface, chunkArea, spawnPos)
|
||||
M.GenerateRailsAndWalls(surface, chunkArea, spawnPos );
|
||||
|
||||
-- careful... arguments for surface and chunkArea are swapped here.
|
||||
|
@ -51,10 +51,10 @@ end
|
||||
|
||||
Event.register(defines.events.on_console_command, on_console_command)
|
||||
|
||||
local function on_research_completed(event)
|
||||
local function on_research_finished(event)
|
||||
logInfo( playerNameFromEvent(event), "+++ research completed: " .. event.research.name );
|
||||
end
|
||||
Event.register(defines.events.on_research_completed, on_research_completed)
|
||||
Event.register(defines.events.on_research_finished, on_research_finished)
|
||||
|
||||
local function on_research_started(event)
|
||||
logInfo( playerNameFromEvent(event), "+++ research started: " .. event.research.name );
|
||||
|
@ -4,7 +4,7 @@
|
||||
local Core = require 'core'
|
||||
local Game = require 'game'
|
||||
|
||||
local debugEvents = false;
|
||||
local debugEvents = true;
|
||||
|
||||
Event = { --luacheck: allow defined top
|
||||
_registry = {},
|
||||
|
@ -10,6 +10,11 @@ function distFunc( cx, cy, ix, iy)
|
||||
return distVar
|
||||
end
|
||||
|
||||
function rangemap( r, from1, from2, to1, to2)
|
||||
local rr = (r-from1)/(from2-from1)
|
||||
return rr*(to2-to1) + to1;
|
||||
end
|
||||
|
||||
function PaveWithConcrete( surface, chunkArea, spawnPos, landRadius)
|
||||
local tiles = {};
|
||||
for y=chunkArea.left_top.y, chunkArea.right_bottom.y-1 do
|
||||
@ -273,36 +278,106 @@ function ShowPlayerSpawns(player)
|
||||
ShowSpawns( player, global.playerSpawns );
|
||||
end
|
||||
|
||||
function DestroyEnemies(chunkArea, surface, spawnPos, radius)
|
||||
local config = spawnGenerator.GetConfig()
|
||||
|
||||
-- don't touch chunks near the silo
|
||||
local w = SILO_RECT_SIZE;
|
||||
local siloRect = MakeRect( -w/2, w, -w/2, w);
|
||||
if ChunkIntersects( chunkArea, siloRect ) then
|
||||
-- silo enemies are handled elsewhere?
|
||||
return
|
||||
-- Clear out enemies around an area with a certain distance
|
||||
function ClearEnemies(surface, position, safeDist)
|
||||
local safeArea = {left_top=
|
||||
{x=position.x-safeDist,
|
||||
y=position.y-safeDist},
|
||||
right_bottom=
|
||||
{x=position.x+safeDist,
|
||||
y=position.y+safeDist}}
|
||||
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = safeArea, force = "enemy"}) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local w = radius
|
||||
local craterArea = MakeRect( spawnPos.x-w, 2*w, spawnPos.y-w, 2*w);
|
||||
if not ChunkIntersects(chunkArea, craterArea) then
|
||||
return
|
||||
end
|
||||
|
||||
-- destroy any enemy in the crater area
|
||||
function ClearNearbyEnemies(surface, chunkArea, spawnPos)
|
||||
-- spawnPos and safeDist are unused now.
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = chunkArea, force = "enemy"}) do
|
||||
if entity ~= nil then
|
||||
local dx = entity.position.x - spawnPos.x;
|
||||
local dy = entity.position.y - spawnPos.y;
|
||||
local dist = math.sqrt(dx*dx+dy*dy);
|
||||
if (dist < radius) then
|
||||
entity.destroy()
|
||||
end
|
||||
if entity ~= nil and entity.valid then
|
||||
local dist = DistanceFromPoint(spawnPos, entity.position);
|
||||
MaybeDestroyEnemy(entity, dist);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ModifyEnemySpawnsNearPlayerStartingAreas(event)
|
||||
|
||||
if (not event.entity or not (event.entity.force.name == "enemy") or not event.entity.position) then
|
||||
log("ModifyBiterSpawns - Unexpected use.")
|
||||
return
|
||||
end
|
||||
|
||||
local enemy_pos = event.entity.position
|
||||
local surface = event.entity.surface
|
||||
|
||||
local closest_spawn = GetClosestUniqueSpawn(surface, enemy_pos)
|
||||
|
||||
if (closest_spawn == nil) then
|
||||
-- log("GetClosestUniqueSpawn ERROR - None found?")
|
||||
return
|
||||
end
|
||||
local dist = DistanceFromPoint(enemy_pos, closest_spawn);
|
||||
MaybeDestroyEnemy( event.entity, dist)
|
||||
end
|
||||
|
||||
function MaybeDestroyEnemy( entity, d)
|
||||
local config = spawnGenerator.GetConfig();
|
||||
if d < config.safe_area.safe_radius then
|
||||
entity.destroy()
|
||||
elseif d < config.safe_area.danger_radius then
|
||||
local p = rangemap( d, config.safe_area.safe_radius, config.safe_area.danger_radius, config.safe_area.warn_reduction_fraction, config.safe_area.warn_reduction_fraction)
|
||||
if math.random() > p then
|
||||
entity.destroy()
|
||||
elseif d < config.safe_area.warn_radius then
|
||||
DowngradeEnemyToSmall( entity )
|
||||
elseif d < config.safe_area.danger_radius then
|
||||
DowngradeEnemyToMedium( entity )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DowngradeEnemyToSmall( entity )
|
||||
local surface = entity.surface;
|
||||
local enemy_name = entity.name;
|
||||
local enemy_pos = entity.position;
|
||||
if ((enemy_name == "big-biter") or (enemy_name == "behemoth-biter") or (enemy_name == "medium-biter")) then
|
||||
entity.destroy()
|
||||
surface.create_entity{name = "small-biter", position = enemy_pos, force = game.forces.enemy}
|
||||
-- log("Downgraded biter close to spawn.")
|
||||
elseif ((enemy_name == "big-spitter") or (enemy_name == "behemoth-spitter") or (enemy_name == "medium-spitter")) then
|
||||
entity.destroy()
|
||||
surface.create_entity{name = "small-spitter", position = enemy_pos, force = game.forces.enemy}
|
||||
-- log("Downgraded spitter close to spawn.")
|
||||
elseif ((enemy_name == "big-worm-turret") or (enemy_name == "behemoth-worm-turret") or (enemy_name == "medium-worm-turret")) then
|
||||
entity.destroy()
|
||||
surface.create_entity{name = "small-worm-turret", position = enemy_pos, force = game.forces.enemy}
|
||||
-- log("Downgraded worm close to spawn.")
|
||||
end
|
||||
end
|
||||
|
||||
function DowngradeEnemyToMedium( entity )
|
||||
local surface = entity.surface;
|
||||
local enemy_name = entity.name;
|
||||
local enemy_pos = entity.position;
|
||||
if ((enemy_name == "big-biter") or (enemy_name == "behemoth-biter")) then
|
||||
entity.destroy()
|
||||
surface.create_entity{name = "medium-biter", position = enemy_pos, force = game.forces.enemy}
|
||||
-- log("Downgraded biter further from spawn.")
|
||||
elseif ((enemy_name == "big-spitter") or (enemy_name == "behemoth-spitter")) then
|
||||
entity.destroy()
|
||||
surface.create_entity{name = "medium-spitter", position = enemy_pos, force = game.forces.enemy}
|
||||
-- log("Downgraded spitter further from spawn
|
||||
elseif ((enemy_name == "big-worm-turret") or (enemy_name == "behemoth-worm-turret")) then
|
||||
entity.destroy()
|
||||
surface.create_entity{name = "medium-worm-turret", position = enemy_pos, force = game.forces.enemy}
|
||||
-- log("Downgraded worm further from spawn.")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function EraseArea(position, chunkDist)
|
||||
local surface = game.surfaces[GAME_SURFACE_NAME];
|
||||
local eraseArea = {left_top=
|
||||
|
@ -269,20 +269,6 @@ function IsChunkAreaUngenerated(chunkPos, chunkDist)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Clear out enemies around an area with a certain distance
|
||||
function ClearNearbyEnemies(player, safeDist)
|
||||
local safeArea = {left_top=
|
||||
{x=player.position.x-safeDist,
|
||||
y=player.position.y-safeDist},
|
||||
right_bottom=
|
||||
{x=player.position.x+safeDist,
|
||||
y=player.position.y+safeDist}}
|
||||
|
||||
for _, entity in pairs(player.surface.find_entities_filtered{area = safeArea, force = "enemy"}) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
-- Function to find coordinates of ungenerated map area in a given direction
|
||||
-- starting from the center of the map
|
||||
function FindMapEdge(directionVec)
|
||||
|
@ -33,15 +33,17 @@ end
|
||||
--end
|
||||
|
||||
function DoGenerateSpawnChunk( surface, chunkArea, spawnPos)
|
||||
local config = spawnGenerator.GetConfig()
|
||||
|
||||
local chunkAreaCenter = {x=chunkArea.left_top.x+(CHUNK_SIZE/2),
|
||||
y=chunkArea.left_top.y+(CHUNK_SIZE/2)}
|
||||
|
||||
local warningArea = {left_top=
|
||||
{x=spawnPos.x-WARNING_AREA_TILE_DIST,
|
||||
y=spawnPos.y-WARNING_AREA_TILE_DIST},
|
||||
{x=spawnPos.x-config.safe_area.warn_radius,
|
||||
y=spawnPos.y-config.safe_area.warn_radius},
|
||||
right_bottom=
|
||||
{x=spawnPos.x+WARNING_AREA_TILE_DIST,
|
||||
y=spawnPos.y+WARNING_AREA_TILE_DIST}}
|
||||
{x=spawnPos.x+config.safe_area.warn_radius,
|
||||
y=spawnPos.y+config.safe_area.warn_radius}}
|
||||
|
||||
if CheckIfChunkIntersects(chunkArea,warningArea) then
|
||||
local config = spawnGenerator.GetConfig()
|
||||
@ -53,11 +55,11 @@ function DoGenerateSpawnChunk( surface, chunkArea, spawnPos)
|
||||
y=spawnPos.y+config.size}}
|
||||
|
||||
local safeArea = {left_top=
|
||||
{x=spawnPos.x-SAFE_AREA_TILE_DIST,
|
||||
y=spawnPos.y-SAFE_AREA_TILE_DIST},
|
||||
{x=spawnPos.x-config.safe_area.safe_radius,
|
||||
y=spawnPos.y-config.safe_area.safe_radius},
|
||||
right_bottom=
|
||||
{x=spawnPos.x+SAFE_AREA_TILE_DIST,
|
||||
y=spawnPos.y+SAFE_AREA_TILE_DIST}}
|
||||
{x=spawnPos.x+config.safe_area.safe_radius,
|
||||
y=spawnPos.y+config.safe_area.safe_radius}}
|
||||
|
||||
|
||||
|
||||
@ -355,20 +357,6 @@ function TeleportPlayerCallback(args)
|
||||
end
|
||||
|
||||
|
||||
-- Clear out enemies around an area with a certain distance
|
||||
function ClearEnemies(surface, position, safeDist)
|
||||
local safeArea = {left_top=
|
||||
{x=position.x-safeDist,
|
||||
y=position.y-safeDist},
|
||||
right_bottom=
|
||||
{x=position.x+safeDist,
|
||||
y=position.y+safeDist}}
|
||||
|
||||
for _, entity in pairs(surface.find_entities_filtered{area = safeArea, force = "enemy"}) do
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function SendPlayerToNewSpawnAndCreateIt(player, spawn)
|
||||
-- Send the player to that position
|
||||
if spawn == nil then
|
||||
@ -393,3 +381,12 @@ function SendPlayerToSpawn(player)
|
||||
end
|
||||
player.teleport(spawn, surface)
|
||||
end
|
||||
|
||||
function GetClosestUniqueSpawn(surface, position)
|
||||
if surface.name == GAME_SURFACE_NAME then
|
||||
return NearestSpawn( global.allSpawns, position);
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user