Factorio: add Traps

This commit is contained in:
Fabian Dill 2021-08-04 05:40:51 +02:00
parent 16701249b4
commit 9408557f03
7 changed files with 173 additions and 64 deletions

View File

@ -16,9 +16,9 @@ from MultiServer import mark_raw
import Utils import Utils
import random import random
from NetUtils import RawJSONtoTextParser, NetworkItem, ClientStatus, JSONtoTextParser, JSONMessagePart from NetUtils import NetworkItem, ClientStatus, JSONtoTextParser, JSONMessagePart
from worlds.factorio.Technologies import lookup_id_to_name from worlds.factorio import Factorio
os.makedirs("logs", exist_ok=True) os.makedirs("logs", exist_ok=True)
@ -196,10 +196,10 @@ async def factorio_server_watcher(ctx: FactorioContext):
transfer_item: NetworkItem = ctx.items_received[ctx.send_index] transfer_item: NetworkItem = ctx.items_received[ctx.send_index]
item_id = transfer_item.item item_id = transfer_item.item
player_name = ctx.player_names[transfer_item.player] player_name = ctx.player_names[transfer_item.player]
if item_id not in lookup_id_to_name: if item_id not in Factorio.item_id_to_name:
logging.error(f"Cannot send unknown item ID: {item_id}") factorio_server_logger.error(f"Cannot send unknown item ID: {item_id}")
else: else:
item_name = lookup_id_to_name[item_id] item_name = Factorio.item_id_to_name[item_id]
factorio_server_logger.info(f"Sending {item_name} to Nauvis from {player_name}.") factorio_server_logger.info(f"Sending {item_name} to Nauvis from {player_name}.")
ctx.rcon_client.send_command(f'/ap-get-technology {item_name}\t{ctx.send_index}\t{player_name}') ctx.rcon_client.send_command(f'/ap-get-technology {item_name}\t{ctx.send_index}\t{player_name}')
ctx.send_index += 1 ctx.send_index += 1

View File

@ -117,6 +117,40 @@ Factorio:
starting_items: starting_items:
burner-mining-drill: 19 burner-mining-drill: 19
stone-furnace: 19 stone-furnace: 19
# Note: Total amount of traps cannot exceed 4, if the sum of them is higher it will get automatically capped.
evolution_traps:
# Trap items that when received increase the enemy evolution.
0: 1
1: 0
2: 0
3: 0
4: 0
random: 0
random-low: 0
random-middle: 0
random-high: 0
evolution_trap_increase:
# If present, % increase of Evolution with each trap received.
5: 0
10: 1
15: 0
20: 0
100: 0
random: 0
random-low: 0
random-middle: 0
random-high: 0
attack_traps:
# Trap items that when received trigger an attack on your base.
0: 1
1: 0
2: 0
3: 0
4: 0
random: 0
random-low: 0
random-middle: 0
random-high: 0
world_gen: world_gen:
# frequency, size, richness, terrain segmentation, starting area and water are all of https://wiki.factorio.com/Types/MapGenSize # frequency, size, richness, terrain segmentation, starting area and water are all of https://wiki.factorio.com/Types/MapGenSize
# inverse of water scale # inverse of water scale

View File

@ -1,7 +1,7 @@
from __future__ import annotations from __future__ import annotations
import typing import typing
from Options import Choice, OptionDict, Option, DefaultOnToggle from Options import Choice, OptionDict, Option, DefaultOnToggle, Range
from schema import Schema, Optional, And, Or from schema import Schema, Optional, And, Or
# schema helpers # schema helpers
@ -125,6 +125,27 @@ class FactorioStartItems(OptionDict):
default = {"burner-mining-drill": 19, "stone-furnace": 19} default = {"burner-mining-drill": 19, "stone-furnace": 19}
class TrapCount(Range):
range_end = 4
class AttackTrapCount(TrapCount):
"""Trap items that when received trigger an attack on your base."""
displayname = "Attack Traps"
class EvolutionTrapCount(TrapCount):
"""Trap items that when received increase the enemy evolution."""
displayname = "Evolution Traps"
class EvolutionTrapIncrease(Range):
displayname = "Evolution Trap % Effect"
range_start = 1
default = 10
range_end = 100
class FactorioWorldGen(OptionDict): class FactorioWorldGen(OptionDict):
displayname = "World Generation" displayname = "World Generation"
# FIXME: do we want default be a rando-optimized default or in-game DS? # FIXME: do we want default be a rando-optimized default or in-game DS?
@ -257,9 +278,11 @@ class FactorioWorldGen(OptionDict):
else: else:
raise NotImplementedError(f"Cannot Convert from non-dictionary, got {type(data)}") raise NotImplementedError(f"Cannot Convert from non-dictionary, got {type(data)}")
class ImportedBlueprint(DefaultOnToggle): class ImportedBlueprint(DefaultOnToggle):
displayname = "Blueprints" displayname = "Blueprints"
factorio_options: typing.Dict[str, type(Option)] = { factorio_options: typing.Dict[str, type(Option)] = {
"max_science_pack": MaxSciencePack, "max_science_pack": MaxSciencePack,
"tech_tree_layout": TechTreeLayout, "tech_tree_layout": TechTreeLayout,
@ -272,5 +295,8 @@ factorio_options: typing.Dict[str, type(Option)] = {
"recipe_ingredients": RecipeIngredients, "recipe_ingredients": RecipeIngredients,
"imported_blueprints": ImportedBlueprint, "imported_blueprints": ImportedBlueprint,
"world_gen": FactorioWorldGen, "world_gen": FactorioWorldGen,
"progressive": Progressive "progressive": Progressive,
"evolution_traps": EvolutionTrapCount,
"attack_traps": AttackTrapCount,
"evolution_trap_increase": EvolutionTrapIncrease,
} }

View File

@ -8,11 +8,10 @@ import string
import Utils import Utils
import logging import logging
import functools
from . import Options from . import Options
factorio_id = 2 ** 17 factorio_id = factorio_base_id = 2 ** 17
source_folder = os.path.join(os.path.dirname(__file__), "data") source_folder = os.path.join(os.path.dirname(__file__), "data")
with open(os.path.join(source_folder, "techs.json")) as f: with open(os.path.join(source_folder, "techs.json")) as f:
@ -38,11 +37,24 @@ class FactorioElement():
class Technology(FactorioElement): # maybe make subclass of Location? class Technology(FactorioElement): # maybe make subclass of Location?
def __init__(self, name: str, ingredients: Set[str], factorio_id: int, progressive: Tuple[str] = ()): has_modifier: bool
factorio_id: int
name: str
ingredients: Set[str]
progressive: Tuple[str]
unlocks: Union[Set[str], bool] # bool case is for progressive technologies
def __init__(self, name: str, ingredients: Set[str], factorio_id: int, progressive: Tuple[str] = (),
has_modifier: bool = False, unlocks: Union[Set[str], bool] = None):
self.name = name self.name = name
self.factorio_id = factorio_id self.factorio_id = factorio_id
self.ingredients = ingredients self.ingredients = ingredients
self.progressive = progressive self.progressive = progressive
self.has_modifier = has_modifier
if unlocks:
self.unlocks = unlocks
else:
self.unlocks = set()
def build_rule(self, player: int): def build_rule(self, player: int):
logging.debug(f"Building rules for {self.name}") logging.debug(f"Building rules for {self.name}")
@ -63,6 +75,9 @@ class Technology(FactorioElement): # maybe make subclass of Location?
def get_custom(self, world, allowed_packs: Set[str], player: int) -> CustomTechnology: def get_custom(self, world, allowed_packs: Set[str], player: int) -> CustomTechnology:
return CustomTechnology(self, world, allowed_packs, player) return CustomTechnology(self, world, allowed_packs, player)
def useful(self) -> bool:
return self.has_modifier or self.unlocks
class CustomTechnology(Technology): class CustomTechnology(Technology):
"""A particularly configured Technology for a world.""" """A particularly configured Technology for a world."""
@ -114,7 +129,7 @@ class Recipe(FactorioElement):
@property @property
def rel_cost(self) -> float: def rel_cost(self) -> float:
ingredients = sum(self.ingredients.values()) ingredients = sum(self.ingredients.values())
return min(ingredients/amount for product, amount in self.products.items()) return min(ingredients / amount for product, amount in self.products.items())
@property @property
def base_cost(self) -> Dict[str, int]: def base_cost(self) -> Dict[str, int]:
@ -122,7 +137,8 @@ class Recipe(FactorioElement):
for ingredient, cost in self.ingredients.items(): for ingredient, cost in self.ingredients.items():
if ingredient in all_product_sources: if ingredient in all_product_sources:
for recipe in all_product_sources[ingredient]: for recipe in all_product_sources[ingredient]:
ingredients.update({name: amount*cost/recipe.products[ingredient] for name, amount in recipe.base_cost.items()}) ingredients.update({name: amount * cost / recipe.products[ingredient] for name, amount in
recipe.base_cost.items()})
else: else:
ingredients[ingredient] += cost ingredients[ingredient] += cost
return ingredients return ingredients
@ -140,33 +156,34 @@ class Recipe(FactorioElement):
break break
return total_energy return total_energy
class Machine(FactorioElement): class Machine(FactorioElement):
def __init__(self, name, categories): def __init__(self, name, categories):
self.name: str = name self.name: str = name
self.categories: set = categories self.categories: set = categories
recipe_sources: Dict[str, Set[str]] = {} # recipe_name -> technology source
# recipes and technologies can share names in Factorio # recipes and technologies can share names in Factorio
for technology_name in sorted(raw): for technology_name in sorted(raw):
data = raw[technology_name] data = raw[technology_name]
current_ingredients = set(data["ingredients"]) current_ingredients = set(data["ingredients"])
technology = Technology(technology_name, current_ingredients, factorio_id) technology = Technology(technology_name, current_ingredients, factorio_id,
has_modifier=data["has_modifier"], unlocks=set(data["unlocks"]))
factorio_id += 1 factorio_id += 1
tech_table[technology_name] = technology.factorio_id tech_table[technology_name] = technology.factorio_id
technology_table[technology_name] = technology technology_table[technology_name] = technology
for recipe_name in technology.unlocks:
recipe_sources: Dict[str, str] = {} # recipe_name -> technology source recipe_sources.setdefault(recipe_name, set()).add(technology_name)
for technology, data in raw.items():
for recipe_name in data["unlocks"]:
recipe_sources.setdefault(recipe_name, set()).add(technology)
del (raw) del (raw)
recipes = {} recipes = {}
all_product_sources: Dict[str, Set[Recipe]] = {"character": set()} all_product_sources: Dict[str, Set[Recipe]] = {"character": set()}
# add uranium mining to logic graph. TODO: add to automatic extractor for mod support # add uranium mining to logic graph. TODO: add to automatic extractor for mod support
raw_recipes["uranium-ore"] = {"ingredients": {"sulfuric-acid": 1}, "products": {"uranium-ore": 1}, "category": "mining", "energy": 2} raw_recipes["uranium-ore"] = {"ingredients": {"sulfuric-acid": 1}, "products": {"uranium-ore": 1}, "category": "mining",
"energy": 2}
for recipe_name, recipe_data in raw_recipes.items(): for recipe_name, recipe_data in raw_recipes.items():
# example: # example:
@ -265,10 +282,9 @@ for category_name, machine_name in machine_per_category.items():
techs |= recursively_get_unlocking_technologies(machine_name) techs |= recursively_get_unlocking_technologies(machine_name)
required_category_technologies[category_name] = frozenset(techs) required_category_technologies[category_name] = frozenset(techs)
required_technologies: Dict[str, FrozenSet[Technology]] = Utils.KeyedDefaultDict(lambda ingredient_name : frozenset( required_technologies: Dict[str, FrozenSet[Technology]] = Utils.KeyedDefaultDict(lambda ingredient_name: frozenset(
recursively_get_unlocking_technologies(ingredient_name, unlock_func=unlock))) recursively_get_unlocking_technologies(ingredient_name, unlock_func=unlock)))
advancement_technologies: Set[str] = set() advancement_technologies: Set[str] = set()
for ingredient_name in all_ingredient_names: for ingredient_name in all_ingredient_names:
technologies = required_technologies[ingredient_name] technologies = required_technologies[ingredient_name]
@ -317,17 +333,17 @@ for tech_name in tech_table:
progressive_incs.add(tech_name) progressive_incs.add(tech_name)
for root, progressive in progressive_rows.items(): for root, progressive in progressive_rows.items():
seeking = root[:-1]+str(int(root[-1])+1) seeking = root[:-1] + str(int(root[-1]) + 1)
while seeking in progressive_incs: while seeking in progressive_incs:
progressive.append(seeking) progressive.append(seeking)
progressive_incs.remove(seeking) progressive_incs.remove(seeking)
seeking = seeking[:-1]+str(int(seeking[-1])+1) seeking = seeking[:-1] + str(int(seeking[-1]) + 1)
# make root entry the progressive name # make root entry the progressive name
for old_name in set(progressive_rows): for old_name in set(progressive_rows):
prog_name = "progressive-" + old_name.rsplit("-", 1)[0] prog_name = "progressive-" + old_name.rsplit("-", 1)[0]
progressive_rows[prog_name] = tuple([old_name] + progressive_rows[old_name]) progressive_rows[prog_name] = tuple([old_name] + progressive_rows[old_name])
del(progressive_rows[old_name]) del (progressive_rows[old_name])
# no -1 start # no -1 start
base_starts = set() base_starts = set()
@ -336,12 +352,12 @@ for remnant in progressive_incs:
base_starts.add(remnant[:-2]) base_starts.add(remnant[:-2])
for root in base_starts: for root in base_starts:
seeking = root+"-2" seeking = root + "-2"
progressive = [root] progressive = [root]
while seeking in progressive_incs: while seeking in progressive_incs:
progressive.append(seeking) progressive.append(seeking)
seeking = seeking[:-1]+str(int(seeking[-1])+1) seeking = seeking[:-1] + str(int(seeking[-1]) + 1)
progressive_rows["progressive-"+root] = tuple(progressive) progressive_rows["progressive-" + root] = tuple(progressive)
# science packs # science packs
progressive_rows["progressive-science-pack"] = tuple(Options.MaxSciencePack.get_ordered_science_packs())[1:] progressive_rows["progressive-science-pack"] = tuple(Options.MaxSciencePack.get_ordered_science_packs())[1:]
@ -381,7 +397,6 @@ source_target_mapping: Dict[str, str] = {
for source, target in source_target_mapping.items(): for source, target in source_target_mapping.items():
progressive_rows[target] += progressive_rows[source] progressive_rows[target] += progressive_rows[source]
base_tech_table = tech_table.copy() # without progressive techs base_tech_table = tech_table.copy() # without progressive techs
base_technology_table = technology_table.copy() base_technology_table = technology_table.copy()
@ -393,7 +408,9 @@ for root in sorted_rows:
assert all(tech in tech_table for tech in progressive) assert all(tech in tech_table for tech in progressive)
factorio_id += 1 factorio_id += 1
progressive_technology = Technology(root, technology_table[progressive_rows[root][0]].ingredients, factorio_id, progressive_technology = Technology(root, technology_table[progressive_rows[root][0]].ingredients, factorio_id,
progressive) progressive,
has_modifier=any(technology_table[tech].has_modifier for tech in progressive),
unlocks=any(technology_table[tech].unlocks for tech in progressive))
progressive_tech_table[root] = progressive_technology.factorio_id progressive_tech_table[root] = progressive_technology.factorio_id
progressive_technology_table[root] = progressive_technology progressive_technology_table[root] = progressive_technology
if any(tech in advancement_technologies for tech in progressive): if any(tech in advancement_technologies for tech in progressive):
@ -412,10 +429,13 @@ technology_table.update(progressive_technology_table)
common_tech_table: Dict[str, int] = {tech_name: tech_id for tech_name, tech_id in base_tech_table.items() common_tech_table: Dict[str, int] = {tech_name: tech_id for tech_name, tech_id in base_tech_table.items()
if tech_name not in progressive_tech_table} if tech_name not in progressive_tech_table}
useless_technologies: Set[str] = {tech_name for tech_name in common_tech_table
if not technology_table[tech_name].useful()}
lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()} lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()}
rel_cost = { rel_cost = {
"wood" : 10000, "wood": 10000,
"iron-ore": 1, "iron-ore": 1,
"copper-ore": 1, "copper-ore": 1,
"stone": 1, "stone": 1,
@ -431,6 +451,7 @@ rel_cost = {
blacklist: Set[str] = all_ingredient_names | {"rocket-part", "crude-oil", "water", "sulfuric-acid", "petroleum-gas", blacklist: Set[str] = all_ingredient_names | {"rocket-part", "crude-oil", "water", "sulfuric-acid", "petroleum-gas",
"light-oil", "heavy-oil", "lubricant", "steam"} "light-oil", "heavy-oil", "lubricant", "steam"}
@Utils.cache_argsless @Utils.cache_argsless
def get_science_pack_pools() -> Dict[str, Set[str]]: def get_science_pack_pools() -> Dict[str, Set[str]]:
def get_estimated_difficulty(recipe: Recipe): def get_estimated_difficulty(recipe: Recipe):
@ -441,7 +462,6 @@ def get_science_pack_pools() -> Dict[str, Set[str]]:
cost += rel_cost.get(ingredient_name, 1) * amount cost += rel_cost.get(ingredient_name, 1) * amount
return cost return cost
science_pack_pools = {} science_pack_pools = {}
already_taken = blacklist.copy() already_taken = blacklist.copy()
current_difficulty = 5 current_difficulty = 5

View File

@ -6,7 +6,7 @@ from BaseClasses import Region, Entrance, Location, Item
from .Technologies import base_tech_table, recipe_sources, base_technology_table, advancement_technologies, \ from .Technologies import base_tech_table, recipe_sources, base_technology_table, advancement_technologies, \
all_ingredient_names, all_product_sources, required_technologies, get_rocket_requirements, rocket_recipes, \ all_ingredient_names, all_product_sources, required_technologies, get_rocket_requirements, rocket_recipes, \
progressive_technology_table, common_tech_table, tech_to_progressive_lookup, progressive_tech_table, \ progressive_technology_table, common_tech_table, tech_to_progressive_lookup, progressive_tech_table, \
get_science_pack_pools, Recipe, recipes, technology_table, tech_table get_science_pack_pools, Recipe, recipes, technology_table, tech_table, factorio_base_id, useless_technologies
from .Shapes import get_shapes from .Shapes import get_shapes
from .Mod import generate_mod from .Mod import generate_mod
from .Options import factorio_options, Silo from .Options import factorio_options, Silo
@ -18,35 +18,48 @@ class FactorioItem(Item):
game = "Factorio" game = "Factorio"
all_items = tech_table.copy()
all_items["Attack Trap"] = factorio_base_id - 1
all_items["Evolution Trap"] = factorio_base_id - 2
class Factorio(World): class Factorio(World):
game: str = "Factorio" game: str = "Factorio"
static_nodes = {"automation", "logistics", "rocket-silo"} static_nodes = {"automation", "logistics", "rocket-silo"}
custom_recipes = {} custom_recipes = {}
additional_advancement_technologies = set() additional_advancement_technologies = set()
item_name_to_id = tech_table item_name_to_id = all_items
location_name_to_id = base_tech_table location_name_to_id = base_tech_table
data_version = 3 data_version = 4
def generate_basic(self): def generate_basic(self):
want_progressives = collections.defaultdict(lambda: self.world.progressive[self.player]. player = self.player
want_progressives = collections.defaultdict(lambda: self.world.progressive[player].
want_progressives(self.world.random)) want_progressives(self.world.random))
skip_silo = self.world.silo[self.player].value == Silo.option_spawn skip_silo = self.world.silo[player].value == Silo.option_spawn
evolution_traps_wanted = self.world.evolution_traps[player].value
attack_traps_wanted = self.world.attack_traps[player].value
traps_wanted = ["Evolution Trap"] * evolution_traps_wanted + ["Attack Trap"] * attack_traps_wanted
self.world.random.shuffle(traps_wanted)
for tech_name in base_tech_table: for tech_name in base_tech_table:
if skip_silo and tech_name == "rocket-silo": if traps_wanted and tech_name in useless_technologies:
continue self.world.itempool.append(self.create_item(traps_wanted.pop()))
elif skip_silo and tech_name == "rocket-silo":
pass
else:
progressive_item_name = tech_to_progressive_lookup.get(tech_name, tech_name) progressive_item_name = tech_to_progressive_lookup.get(tech_name, tech_name)
want_progressive = want_progressives[progressive_item_name] want_progressive = want_progressives[progressive_item_name]
item_name = progressive_item_name if want_progressive else tech_name item_name = progressive_item_name if want_progressive else tech_name
tech_item = self.create_item(item_name) tech_item = self.create_item(item_name)
if tech_name in self.static_nodes: if tech_name in self.static_nodes:
self.world.get_location(tech_name, self.player).place_locked_item(tech_item) self.world.get_location(tech_name, player).place_locked_item(tech_item)
else: else:
self.world.itempool.append(tech_item) self.world.itempool.append(tech_item)
map_basic_settings = self.world.world_gen[self.player].value["basic"] map_basic_settings = self.world.world_gen[player].value["basic"]
if map_basic_settings.get("seed", None) is None: # allow seed 0 if map_basic_settings.get("seed", None) is None: # allow seed 0
map_basic_settings["seed"] = self.world.slot_seeds[self.player].randint(0, 2**32-1) # 32 bit uint map_basic_settings["seed"] = self.world.slot_seeds[player].randint(0, 2 ** 32 - 1) # 32 bit uint
generate_output = generate_mod generate_output = generate_mod
@ -263,7 +276,9 @@ class Factorio(World):
self.additional_advancement_technologies |= prog_add self.additional_advancement_technologies |= prog_add
def create_item(self, name: str) -> Item: def create_item(self, name: str) -> Item:
assert name in tech_table if name in tech_table:
return FactorioItem(name, name in advancement_technologies or return FactorioItem(name, name in advancement_technologies or
name in self.additional_advancement_technologies, name in self.additional_advancement_technologies,
tech_table[name], self.player) tech_table[name], self.player)
elif name in all_items:
return FactorioItem(name, False, all_items[name], self.player)

View File

@ -7,6 +7,7 @@ FREE_SAMPLES = {{ free_samples }}
SLOT_NAME = "{{ slot_name }}" SLOT_NAME = "{{ slot_name }}"
SEED_NAME = "{{ seed_name }}" SEED_NAME = "{{ seed_name }}"
FREE_SAMPLE_BLACKLIST = {{ dict_to_lua(free_sample_blacklist) }} FREE_SAMPLE_BLACKLIST = {{ dict_to_lua(free_sample_blacklist) }}
TRAP_EVO_FACTOR = {{ evolution_trap_increase }} / 100
{% if not imported_blueprints -%} {% if not imported_blueprints -%}
function set_permissions() function set_permissions()
@ -369,15 +370,15 @@ commands.add_command("ap-get-technology", "Grant a technology, used by the Archi
local tech local tech
local force = game.forces["player"] local force = game.forces["player"]
chunks = split(call.parameter, "\t") chunks = split(call.parameter, "\t")
local tech_name = chunks[1] local item_name = chunks[1]
local index = chunks[2] local index = chunks[2]
local source = chunks[3] or "Archipelago" local source = chunks[3] or "Archipelago"
if progressive_technologies[tech_name] ~= nil then if progressive_technologies[item_name] ~= nil then
if global.index_sync[index] == nil then -- not yet received prog item if global.index_sync[index] == nil then -- not yet received prog item
global.index_sync[index] = tech_name global.index_sync[index] = item_name
local tech_stack = progressive_technologies[tech_name] local tech_stack = progressive_technologies[item_name]
for _, tech_name in ipairs(tech_stack) do for _, item_name in ipairs(tech_stack) do
tech = force.technologies[tech_name] tech = force.technologies[item_name]
if tech.researched ~= true then if tech.researched ~= true then
game.print({"", "Received [technology=" .. tech.name .. "] from ", source}) game.print({"", "Received [technology=" .. tech.name .. "] from ", source})
game.play_sound({path="utility/research_completed"}) game.play_sound({path="utility/research_completed"})
@ -386,8 +387,8 @@ commands.add_command("ap-get-technology", "Grant a technology, used by the Archi
end end
end end
end end
elseif force.technologies[tech_name] ~= nil then elseif force.technologies[item_name] ~= nil then
tech = force.technologies[tech_name] tech = force.technologies[item_name]
if tech ~= nil then if tech ~= nil then
if global.index_sync[index] ~= nil and global.index_sync[index] ~= tech then if global.index_sync[index] ~= nil and global.index_sync[index] ~= tech then
game.print("Warning: Desync Detected. Duplicate/Missing items may occur.") game.print("Warning: Desync Detected. Duplicate/Missing items may occur.")
@ -399,8 +400,21 @@ commands.add_command("ap-get-technology", "Grant a technology, used by the Archi
tech.researched = true tech.researched = true
end end
end end
elseif item_name == "Attack Trap" then
if global.index_sync[index] == nil then -- not yet received trap
game.print({"", "Received Attack Trap from ", source})
global.index_sync[index] = item_name
local spawn_position = force.get_spawn_position(game.get_surface(1))
game.surfaces["nauvis"].build_enemy_base(spawn_position, 25)
end
elseif item_name == "Evolution Trap" then
if global.index_sync[index] == nil then -- not yet received trap
global.index_sync[index] = item_name
game.forces["enemy"].evolution_factor = game.forces["enemy"].evolution_factor + TRAP_EVO_FACTOR
game.print({"", "Received Evolution Trap from ", source, ". New factor:", game.forces["enemy"].evolution_factor})
end
else else
game.print("Unknown Technology " .. tech_name) game.print("Unknown Item " .. item_name)
end end
end) end)

File diff suppressed because one or more lines are too long