local util = require("__Kombat_Drones__/data/tf_util/tf_util") local add_icons = function(icons, addition) for k, v in pairs (addition) do table.insert(icons, v) end end local get_icons = function(prototype) return util.copy(prototype.icons or {{icon = prototype.icon, icon_size = prototype.icon_size}}) end local shift_icons = function(icons, shift) for k, v in pairs (icons) do v.shift = v.shift or {0,0} v.shift[1] = v.shift[1] + shift[1] v.shift[2] = v.shift[2] + shift[2] end end local scale_icons = function(icons, scale) for k, v in pairs (icons) do v.scale = (v.scale or 1) * scale end end local get_localised_item_name = function(prototype) return prototype.localised_name or {"item-name."..prototype.name} end local get_ammo_type = function(prototype) local ammo_type = util.copy(prototype.ammo_type) if ammo_type[1] then for k, v in pairs (ammo_type) do if v.source_type and v.source_type == "player" then return v end end for k, v in pairs (ammo_type) do if v.source_type and v.source_type == "default" then return v end end end return ammo_type end local recursive_find_table_with_key recursive_find_table_with_key = function(results, table, search) for key, value in pairs (table) do if key == search then results[table] = true end if type(value) == "table" then recursive_find_table_with_key(results, value, search) end end end local projectiles = util.copy(data.raw.projectile) for k, v in pairs (data.raw["artillery-projectile"]) do projectiles[k] = v end local dupe_projectile = function(projectile_name) local projectile = util.copy(projectiles[projectile_name]) if not projectile then error(projectile_name) end if projectile.force_condition then return projectile.name end projectile.name = projectile.name.."-no-hit-ally" projectile.force_condition = "not-same" data:extend{projectile} return projectile.name end local fix_shotgun = function(ammo_type) local trigger_effects = {} recursive_find_table_with_key(trigger_effects, ammo_type, "projectile") for trigger, bool in pairs (trigger_effects) do trigger.projectile = dupe_projectile(trigger.projectile) end end local make_icons = function(chassis, gun, ammo) local icons = get_icons(chassis) shift_icons(icons, {0, -8}) scale_icons(icons, 0.8) local ammo_icons = get_icons(ammo) shift_icons(ammo_icons, {10, 8}) scale_icons(ammo_icons, 0.4) add_icons(icons, ammo_icons) local gun_icons = get_icons(gun) shift_icons(gun_icons, {-10, 8}) scale_icons(gun_icons, 0.4) add_icons(icons, gun_icons) return icons end local make_unarmed_icons = function(chassis) local icons = get_icons(chassis) shift_icons(icons, {0, -8}) scale_icons(icons, 0.8) local tech_icon = { icon = "__base__/graphics/technology/steel-axe.png", icon_size = 256, icon_scale = 0.18, shift = {10, 8} } add_icons(icons, {tech_icon}) return icons end local make_chassis = function(chassis, gun, ammo) local bot = util.copy(chassis) local attack_parameters = util.copy(gun.attack_parameters) attack_parameters.ammo_type = get_ammo_type(ammo) fix_shotgun(attack_parameters.ammo_type) attack_parameters.range = attack_parameters.range * (attack_parameters.ammo_type.range_modifier or 1) attack_parameters.min_attack_distance = attack_parameters.range * 0.9 attack_parameters.cooldown_deviation = attack_parameters.cooldown_deviation or 0.1 attack_parameters.ammo_type.range_modifier = nil attack_parameters.animation = bot.attack_animation bot.move_while_shooting = (attack_parameters.cooldown > 15) bot.rotation_speed = 5 / 60 bot.icon = nil bot.icons = make_icons(chassis, gun, ammo) bot.attack_parameters = attack_parameters bot.localised_name = { "", bot.localised_name, "\n[item="..gun.name.."] ", get_localised_item_name(gun), "\n[item="..ammo.name.."] ", get_localised_item_name(ammo) } bot.name = bot.name.."-"..gun.name.."-"..ammo.name bot.vision_distance = math.max(math.min(80, attack_parameters.range + 10), 25) bot.max_pursue_distance = 200 bot.distraction_cooldown = 29 bot.placeable_by = {{item = chassis.name, count = 1}} data:extend{bot} end local frame_time = 30 local unarmed_attack_parameters = { type = "projectile", range = 0.5, warmup = 19, cooldown = 28 - 19, cooldown_deviation = 0.1, ammo_type = { category = "melee", target_type = "entity", action = { type = "direct", action_delivery = { type = "instant", target_effects = { type = "damage", damage = { amount = 10, type = "physical"} }, source_effects = { type = "play-sound", sound = data.raw["utility-sounds"].default.axe_fighting } } }, }, ammo_category = "melee", range_mode = "bounding-box-to-bounding-box" } local make_unarmed_chassis = function(chassis) local bot = util.copy(chassis) local attack_parameters = util.copy(unarmed_attack_parameters) attack_parameters.animation = bot.mining_animation attack_parameters.damage_modifier = bot.melee_strength bot.move_while_shooting = false bot.rotation_speed = 5 / 60 --bot.icon = nil bot.icons = make_unarmed_icons(chassis) bot.attack_parameters = attack_parameters bot.localised_name = { "", bot.localised_name, "\n [technology=steel-axe]", {"unarmed"} } bot.name = bot.name.."-unarmed" bot.vision_distance = math.max(math.min(80, attack_parameters.range + 10), 25) bot.max_pursue_distance = 200 bot.distraction_cooldown = 19 bot.run_animation = bot.run_unarmed_animation bot.movement_speed = bot.movement_speed * 1.1 data:extend{bot} end local base = util.copy(data.raw.character.character) local corpse_base = util.copy(data.raw["character-corpse"]["character-corpse"]) util.recursive_hack_something(corpse_base, "direction_count", 1) local character_sprites = require(util.path("data/entities/units/character_sprites/character_sprites")) local light_running_with_gun = util.copy( { layers = { character_sprites.running_gun, character_sprites.running_gun_mask, character_sprites.running_gun_shadow, } }) local light_running = util.copy(base.animations[1].running) local light_shooting = util.copy(base.animations[1].idle_with_gun) local light_mining = util.copy(base.animations[1].mining_with_tool) local light_corpse = util.copy(corpse_base.pictures[1]) local heavy_running_with_gun = util.copy { layers = { character_sprites.running_gun, character_sprites.running_gun_armor, character_sprites.running_gun_mask, character_sprites.running_gun_armor_mask, character_sprites.running_gun_shadow, } } local heavy_running = util.copy(base.animations[2].running) local heavy_shooting = util.copy(base.animations[2].idle_with_gun) local heavy_mining = util.copy(base.animations[2].mining_with_tool) local heavy_corpse = util.copy(corpse_base.pictures[2]) util.recursive_hack_scale(heavy_running_with_gun, 1.25) util.recursive_hack_scale(heavy_running, 1.25) util.recursive_hack_scale(heavy_shooting, 1.25) util.recursive_hack_scale(heavy_mining, 1.25) util.recursive_hack_scale(heavy_corpse, 1.25) local power_running_with_gun = util.copy { layers = { character_sprites.running_gun, character_sprites.running_gun_armor_2, character_sprites.running_gun_mask, character_sprites.running_gun_armor_mask_2, character_sprites.running_gun_shadow, } } local power_running_with_gun = util.copy { layers = { character_sprites.running_gun, character_sprites.running_gun_armor_2, character_sprites.running_gun_mask, character_sprites.running_gun_armor_mask_2, character_sprites.running_gun_shadow, } } local power_running = util.copy(base.animations[3].running) local power_shooting = util.copy(base.animations[3].idle_with_gun) local power_mining = util.copy(base.animations[3].mining_with_tool) local power_corpse = util.copy(corpse_base.pictures[3]) util.recursive_hack_scale(power_running_with_gun, 1.4) util.recursive_hack_scale(power_running, 1.4) util.recursive_hack_scale(power_shooting, 1.4) util.recursive_hack_scale(power_mining, 1.4) util.recursive_hack_scale(power_corpse, 1.4) local chassis_types = { ["basic-infantry"] = { type = "unit", name = "basic-infantry", localised_name = {"basic-infantry"}, icon = "__Kombat_Drones__/data/entities/depots/infantry_depot/light-chassis-icon.png", icon_size = 64, map_color = {b = 0.5, g = 1}, enemy_map_color = {r = 1}, max_health = 150, radar_range = 2, order="i-a", --subgroup = "iron-units", can_open_gates = true, healing_per_tick = 0.05, --minable = {result = name, mining_time = 2}, collision_box = {{-0.5, -0.5}, {0.5, 0.5}}, collision_mask = util.ground_unit_collision_mask(), max_pursue_distance = 64, resistances = nil, min_persue_time = 60 * 15, selection_box = {{-0.5, -0.5}, {0.5, 0.5}}, sticker_box = {{-0.3, -1}, {0.2, 0.3}}, distraction_cooldown = 12, move_while_shooting = true, can_open_gates = true, ai_settings = { do_separation = true }, vision_distance = 100, has_belt_immunity = true, trigger_target_mask = {"common"}, affected_by_tiles = true, movement_speed = 0.15, distance_per_frame = 0.15, absorbtions_to_join_attack = 1000, --corpse = name.." Corpse", --dying_explosion = "explosion", run_animation = light_running_with_gun, attack_animation = light_shooting, mining_animation = light_mining, run_unarmed_animation = light_running, corpse_animation = light_corpse, melee_strength = 1, resistances = util.copy(data.raw.armor["light-armor"].resistances), hide_resistances = false, light = { { type = "oriented", minimum_darkness = 0.3, picture = { filename = "__core__/graphics/light-cone.png", priority = "extra-high", flags = { "light" }, scale = 2, width = 200, height = 200 }, shift = {0, -13}, size = 2, intensity = 0.6, color = {r=1.0, g=1.0, b=1.0} } } }, ["heavy-infantry"] = { type = "unit", name = "heavy-infantry", localised_name = {"heavy-infantry"}, icon = "__Kombat_Drones__/data/entities/depots/infantry_depot/heavy-chassis-icon.png", icon_size = 64, --flags = util.unit_flags(), map_color = {b = 0.5, g = 1}, enemy_map_color = {r = 1}, max_health = 250, radar_range = 2, order="i-a", can_open_gates = true, healing_per_tick = 0.075, --minable = {result = name, mining_time = 2}, collision_box = {{-0.66, -0.66}, {0.66, 0.66}}, collision_mask = util.ground_unit_collision_mask(), max_pursue_distance = 64, resistances = nil, min_persue_time = 60 * 15, selection_box = {{-0.66, -0.66}, {0.66, 0.66}}, sticker_box = {{-0.3, -1}, {0.2, 0.3}}, distraction_cooldown = 12, move_while_shooting = true, can_open_gates = true, ai_settings = { do_separation = true }, vision_distance = 100, has_belt_immunity = true, trigger_target_mask = {"common"}, affected_by_tiles = true, movement_speed = 0.125, distance_per_frame = 0.15, absorbtions_to_join_attack = 1000, --corpse = name.." Corpse", --dying_explosion = "explosion", run_animation = heavy_running_with_gun, attack_animation = heavy_shooting, mining_animation = heavy_mining, run_unarmed_animation = heavy_running, corpse_animation = heavy_corpse, melee_strength = 1.5, resistances = util.copy(data.raw.armor["heavy-armor"].resistances), hide_resistances = false, light = { { type = "oriented", minimum_darkness = 0.3, picture = { filename = "__core__/graphics/light-cone.png", priority = "extra-high", flags = { "light" }, scale = 2, width = 200, height = 200 }, shift = {0, -6.5 * 2.4}, size = 2.4, intensity = 0.6, color = {r=1.0, g=1.0, b=1.0} } } }, ["power-infantry"] = { type = "unit", name = "power-infantry", localised_name = {"power-infantry"}, icon = "__Kombat_Drones__/data/entities/depots/infantry_depot/power-chassis-icon.png", icon_size = 64, --flags = util.unit_flags(), map_color = {b = 0.5, g = 1}, enemy_map_color = {r = 1}, max_health = 350, radar_range = 2, order="i-a", can_open_gates = true, healing_per_tick = 0.1, --minable = {result = name, mining_time = 2}, collision_box = {{-0.75, -0.75}, {0.75, 0.75}}, collision_mask = util.ground_unit_collision_mask(), max_pursue_distance = 64, resistances = nil, min_persue_time = 60 * 15, selection_box = {{-0.75, -0.75}, {0.75, 0.75}}, sticker_box = {{-0.3, -1}, {0.2, 0.3}}, distraction_cooldown = 12, move_while_shooting = true, can_open_gates = true, ai_settings = { do_separation = true }, vision_distance = 100, has_belt_immunity = true, trigger_target_mask = {"common"}, affected_by_tiles = true, movement_speed = 0.11, distance_per_frame = 0.15, absorbtions_to_join_attack = 1000, --corpse = name.." Corpse", --dying_explosion = "explosion", run_animation = power_running_with_gun, attack_animation = power_shooting, mining_animation = power_mining, run_unarmed_animation = power_running, corpse_animation = power_corpse, melee_strength = 2.5, resistances = util.copy(data.raw.armor["modular-armor"].resistances), hide_resistances = false, light = { { type = "oriented", minimum_darkness = 0.3, picture = { filename = "__core__/graphics/light-cone.png", priority = "extra-high", flags = { "light" }, scale = 2, width = 200, height = 200 }, shift = {0, -6.5 * 3}, size = 3, intensity = 0.6, color = {r=1.0, g=1.0, b=1.0} } } } } for k, chassis in pairs (chassis_types) do local item = { type = "item", name = chassis.name, localised_name = chassis.localised_name, icon = chassis.icon, icon_size = chassis.icon_size, stack_size = 10, order = "a-"..chassis.name, subgroup = "gun" } local group = { type = "item-group", name = chassis.name, order = "a-"..chassis.name, localised_name = chassis.localised_name, icon = chassis.icon, icon_size = chassis.icon_size } data:extend { item, group } end local get_ammos_for_gun = function(gun) local ammos = {} for k, ammo in pairs (data.raw.ammo) do if get_ammo_type(ammo).category == gun.attack_parameters.ammo_category then ammos[k] = ammo end end return ammos end local make_depot_recipe = function(chassis, gun, ammo) local name = chassis.name.."-"..gun.name.."-"..ammo.name local recipe = { type = "recipe", name = name, localised_name = { "", {"deploy"}, " ", chassis.localised_name, "\n[item="..gun.name.."] ", get_localised_item_name(gun), "\n[item="..ammo.name.."] ", get_localised_item_name(ammo), "\n" }, ingredients = { {type = "item", name = chassis.name, amount = 1}, {type = "item", name = gun.name, amount = 1}, {type = "item", name = ammo.name, amount = 10} }, energy_required = 10, category = "infantry-depot", subgroup = util.subgroup(chassis.name, gun.attack_parameters.ammo_category or "poop"), results = {{type="item", name=name, amount=1}}, icons = make_icons(chassis, gun, ammo), order = gun.order..ammo.order, hide_from_player_crafting = true } data:extend{recipe} end local make_unarmed_depot_recipe = function(chassis) local name = chassis.name.."-unarmed" local recipe = { type = "recipe", name = name, localised_name = { "", {"deploy"}, " ", chassis.localised_name, "\n[technology=steel-axe] ", {"unarmed"}, "\n" }, ingredients = { {type = "item", name = chassis.name, amount = 1} }, energy_required = 10, category = "infantry-depot", subgroup = util.subgroup(chassis.name, "a-a-unarmed"), results = {{type="item", name=name, amount=1}}, icons = make_unarmed_icons(chassis), order = "a-a-unarmed", hide_from_player_crafting = true } data:extend{recipe} end local make_chassis_item = function(chassis, gun, ammo) local item = { type = "item", name = chassis.name.."-"..gun.name.."-"..ammo.name, localised_name = { "", chassis.localised_name, "\n[item="..gun.name.."] ", get_localised_item_name(gun), "\n[item="..ammo.name.."] ", get_localised_item_name(ammo) }, icons = make_icons(chassis, gun, ammo), stack_size = 1 } data:extend{item} end local make_unarmed_chassis_item = function(chassis) local item = { type = "item", name = chassis.name.."-unarmed", localised_name = { "", chassis.localised_name, "\n[technology=steel-axe] ", {"unarmed"}, }, icons = make_unarmed_icons(chassis), stack_size = 1 } data:extend{item} end local make_corpse = function(chassis) local corpse = { type = "corpse", name = chassis.name.."-corpse", localised_name = chassis.name.."-corpse", icon = "__base__/graphics/icons/remnants.png", icon_size = 64, icon_mipmaps = 4, flags = {"placeable-neutral", "building-direction-8-way", "not-on-map"}, subgroup = "generic-remnants", order = "a-a-a", selection_box = {{-0.5, -0.5}, {0.5, 0.5}}, selectable_in_game = false, time_before_removed = 60 * 60 * 15, -- 15 minutes final_render_layer = "remnants", remove_on_tile_placement = false, animation = chassis.corpse_animation } data:extend{corpse} chassis.corpse = chassis.name.."-corpse" end for k, chassis in pairs (chassis_types) do make_corpse(chassis) make_unarmed_chassis(chassis) make_unarmed_chassis_item(chassis) make_unarmed_depot_recipe(chassis) end local process_gun = function(gun) local ammos = get_ammos_for_gun(gun) for k, chassis in pairs (chassis_types) do for k, ammo in pairs (ammos) do make_chassis(chassis, gun, ammo) make_chassis_item(chassis, gun, ammo) make_depot_recipe(chassis, gun, ammo) end end end local guns = data.raw.gun local recipes = data.raw.recipe for k, tech in pairs (data.raw.technology) do for k, effect in pairs (tech.effects or {}) do if effect.type == "unlock-recipe" then if recipes[effect.recipe] then recipes[effect.recipe].is_unlockable_for_techs_cool = true end end end end for k, recipe in pairs (recipes) do if recipe.is_unlockable_for_techs_cool or (recipe.enabled ~= false) then local products = {} local recipe = recipe.normal or recipe if recipe.result then table.insert(products, recipe.result) end if recipe.results then for maybe_name, result in pairs (recipe.results) do if result[1] then table.insert(products, result[1]) else table.insert(products, result.name) end end end for k, name in pairs (products) do if guns[name] then guns[name].has_recipe_for_it_cool = true end end end recipe.is_unlockable_for_techs_cool = nil end for k, gun in pairs (data.raw.gun) do if gun.has_recipe_for_it_cool then process_gun(gun) end gun.has_recipe_for_it_cool = nil end --[[ local basic_tech = data.raw.technology["infantry-depot"] local heavy_tech = data.raw.technology["heavy-infantry"] local power_tech = data.raw.technology["power-infantry"] for name, unit in pairs (data.raw.unit) do if name:find("basic-infantry", 0, true) then table.insert(basic_tech.effects, { type = "unlock-recipe", recipe = name }) end if name:find("heavy-infantry", 0, true) then table.insert(heavy_tech.effects, { type = "unlock-recipe", recipe = name }) end if name:find("power-infantry", 0, true) then table.insert(power_tech.effects, { type = "unlock-recipe", recipe = name }) end end ]]