2020-02-15 22:03:25 -05:00
-- oarc_enemies.lua
-- Feb 2020
-- This is my second attempt at modifying the normal enemy experience. The
-- first attempt ended up in a wave attack system which wasn't well received.
-- This attempt will try to intercept normal vanilla enemy groups and modify
-- them based on player activity.
-- Basic logic:
2020-02-16 19:57:10 -05:00
-- on_unit_group_finished_gathering we check what command is given.
-- find destination position
2020-02-15 22:03:25 -05:00
-- check for closest "player" using find_nearest_enemy function
-- if a player is found, check if player is part of a shared spawn
-- Remove the enemy group if no player in the shared spawn is online.
-- TODO:
-- Add options for modifying the default waves or spawning additional special waves.
-- Add option to disable attacks completely for a given spawn.
-- Generic Utility Includes
require ( " lib/oarc_utils " )
function OarcModifyEnemyGroup ( group )
2020-02-16 19:57:10 -05:00
-- Check validity
if ( ( group == nil ) or ( group.command == nil ) or ( group.force . name ~= " enemy " ) ) then
log ( " OarcModifyEnemyGroup ignoring INVALID group/command " )
return
end
-- Make sure the attack is of a TYPE that we care about.
if ( ( group.command . type == defines.command . attack ) or
( group.command . type == defines.command . attack_area ) or
( group.command . type == defines.command . build_base ) ) then
log ( " OarcModifyEnemyGroup MODIFYING command TYPE= " .. group.command . type )
else
log ( " OarcModifyEnemyGroup ignoring command TYPE= " .. group.command . type )
return
end
-- defines.command.attack --> target --> target.position
if ( group.command . type == defines.command . attack ) then
log ( " OarcModifyEnemyGroup defines.command.attack NOT IMPLEMENTED YET! " )
return
-- defines.command.attack_area --> destination --> closest enemy (within 3 chunk radius?)
-- defines.command.build_base --> destination --> closest enemy (expansion chunk distance?)
else
local destination = group.command . destination
local distance = CHUNK_SIZE * 3
if ( group.command . type == defines.command . build_base ) then
2020-03-20 14:01:37 -04:00
distance = CHUNK_SIZE * ( game.map_settings . enemy_expansion.max_expansion_distance )
2020-02-16 19:57:10 -05:00
end
2020-02-25 14:56:49 -05:00
-- Find some enemies near the attack point.
local target_entities = group.surface . find_entities_filtered {
position = destination ,
radius = distance ,
force = { " enemy " , " neutral " } ,
limit = 50 ,
invert = true }
-- Search through them all to find anything with a last_user.
local target_entity = nil
for _ , target in ipairs ( target_entities ) do
if ( target.last_user ~= nil ) then
target_entity = target
break
end
end
2020-02-15 22:03:25 -05:00
-- No enemies nearby?
if ( target_entity == nil ) then
2020-02-16 19:57:10 -05:00
if ( group.command . type == defines.command . attack_area ) then
if ( global.enable_oe_debug ) then
2020-02-25 14:56:49 -05:00
SendBroadcastMsg ( " OarcModifyEnemyGroup find_nearest_enemy attack_area FAILED!?!? " .. GetGPStext ( group.position ) .. " Target: " .. GetGPStext ( destination ) )
2020-02-16 19:57:10 -05:00
end
log ( " OarcModifyEnemyGroup UNEXPECTED find_nearest_enemy did not find anything! " )
2020-02-25 14:56:49 -05:00
for _ , member in pairs ( group.members ) do
member.destroy ( )
end
2020-02-16 19:57:10 -05:00
else
log ( " OarcModifyEnemyGroup find_nearest_enemy did not find anything! " )
end
return
2020-02-15 22:03:25 -05:00
end
-- Probably don't need this I hope?
if ( target_entity.force == " neutral " ) then
2020-02-16 19:57:10 -05:00
log ( " OarcModifyEnemyGroup UNEXPECTED find_nearest_enemy found neutral target? " )
2020-02-25 14:56:49 -05:00
for _ , member in pairs ( group.members ) do
member.destroy ( )
end
2020-02-16 19:57:10 -05:00
return
2020-02-15 22:03:25 -05:00
end
2020-02-15 23:16:38 -05:00
-- Most common target will be a built entity with a "last_user"
2020-02-15 22:03:25 -05:00
local target_player = target_entity.last_user
2020-02-15 23:16:38 -05:00
-- Target could also be a player character (more rare)
if ( target_player == nil ) and ( target_entity.type == " character " ) then
2020-02-16 19:57:10 -05:00
target_player = target_entity.player
2020-02-15 22:03:25 -05:00
end
2020-02-15 23:16:38 -05:00
-- I don't think this should happen...
if ( ( target_player == nil ) or ( not target_player.valid ) ) then
2020-02-16 19:57:10 -05:00
if ( global.enable_oe_debug ) then
2020-02-25 14:56:49 -05:00
SendBroadcastMsg ( " ERROR?? target_player nil/invalid " .. GetGPStext ( group.position ) .. " Target: " .. GetGPStext ( target_entity.position ) )
2020-02-16 19:57:10 -05:00
end
log ( " OarcModifyEnemyGroup ERROR?? target_player nil/invalid " )
2020-02-25 14:56:49 -05:00
for _ , member in pairs ( group.members ) do
member.destroy ( )
end
2020-02-16 19:57:10 -05:00
return
2020-02-15 22:03:25 -05:00
end
-- Is the target player online? Then the attack can go through.
if ( target_player.connected ) then
2020-02-16 19:57:10 -05:00
if ( global.enable_oe_debug ) then
2020-02-25 14:56:49 -05:00
SendBroadcastMsg ( " Enemy group released (player): " .. GetGPStext ( group.position ) .. " Target: " .. GetGPStext ( target_entity.position ) .. " " .. target_player.name )
2020-02-16 19:57:10 -05:00
end
log ( " OarcModifyEnemyGroup RELEASING enemy group since player is ONLINE " )
return
2020-02-15 22:03:25 -05:00
end
-- Find the shared spawn that the player is part of.
-- This could be the own player's spawn (quite likely)
2020-02-16 19:57:10 -05:00
local sharedSpawnOwnerName = FindPlayerSharedSpawn ( target_player.name )
2020-02-15 22:03:25 -05:00
-- Is someone in the shared spawn online?
2020-02-16 19:57:10 -05:00
if ( sharedSpawnOwnerName ~= nil ) then
if ( GetOnlinePlayersAtSharedSpawn ( sharedSpawnOwnerName ) > 0 ) then
if ( global.enable_oe_debug ) then
2020-02-25 14:56:49 -05:00
SendBroadcastMsg ( " Enemy group released (shared): " .. GetGPStext ( group.position ) .. " Target: " .. GetGPStext ( target_entity.position ) .. " " .. target_player.name )
2020-02-16 19:57:10 -05:00
end
log ( " OarcModifyEnemyGroup RELEASING enemy group since someone in the group is ONLINE " )
return
end
2020-02-15 22:03:25 -05:00
end
2020-02-16 14:30:27 -05:00
-- Is there a buddy spawn and is the buddy online?
2020-02-16 19:57:10 -05:00
local buddyName = global.buddyPairs [ sharedSpawnOwnerName ]
if ( buddyName ~= nil ) and ( game.players [ buddyName ] ~= nil ) then
if ( game.players [ buddyName ] . connected or ( GetOnlinePlayersAtSharedSpawn ( buddyName ) > 0 ) ) then
if ( global.enable_oe_debug ) then
2020-02-25 14:56:49 -05:00
SendBroadcastMsg ( " Enemy group released (buddy): " .. GetGPStext ( group.position ) .. " Target: " .. GetGPStext ( target_entity.position ) .. " " .. target_player.name )
2020-02-16 19:57:10 -05:00
end
log ( " OarcModifyEnemyGroup RELEASING enemy group since someone in the BUDDY PAIR is ONLINE " )
return
end
2020-02-16 14:30:27 -05:00
end
2020-02-15 22:03:25 -05:00
-- Otherwise, we delete the group.
2020-02-16 15:32:31 -05:00
if ( global.enable_oe_debug ) then
2020-02-25 14:56:49 -05:00
SendBroadcastMsg ( " Enemy group deleted: " .. GetGPStext ( group.position ) .. " Target: " .. GetGPStext ( target_entity.position ) .. " " .. target_player.name )
2020-02-16 19:57:10 -05:00
end
2020-02-15 22:03:25 -05:00
for _ , member in pairs ( group.members ) do
2020-02-16 19:57:10 -05:00
member.destroy ( )
2020-02-15 22:03:25 -05:00
end
log ( " OarcModifyEnemyGroup REMOVED enemy group since nobody was online? " )
2020-02-16 19:57:10 -05:00
end
2020-02-15 22:03:25 -05:00
end