1
0
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:
Kevin Morgan 2020-08-31 13:36:10 -07:00
parent 281b708012
commit 95122a8a5f
10 changed files with 179 additions and 101 deletions

View File

@ -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,
}

View File

@ -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
View File

@ -0,0 +1,4 @@
{
"order": "a",
"multiplayer-compatible": true
}

View File

@ -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

View File

@ -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.

View File

@ -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 );

View File

@ -4,7 +4,7 @@
local Core = require 'core'
local Game = require 'game'
local debugEvents = false;
local debugEvents = true;
Event = { --luacheck: allow defined top
_registry = {},

View File

@ -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=

View File

@ -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)

View File

@ -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