diff --git a/changelog.txt b/changelog.txt index fe00a00..d48c97f 100755 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,8 @@ Date: 2. 02. 2018 Improvements: - Changed defualt for friendly fire to off for worm and spitter splash damage - Generating unit spawner probabilities for each tier instead of sharing a single table + - Changed electric biters to target multiple entities with their beams at a time + - Changed electric worms to shoot a projectile that explodes into an electrical cluster --------------------------------------------------------------------------------------------------- Version: 0.16.16 diff --git a/prototypes/Electric.lua b/prototypes/Electric.lua index 4190c78..18093d1 100755 --- a/prototypes/Electric.lua +++ b/prototypes/Electric.lua @@ -2,6 +2,7 @@ local biterUtils = require("utils/BiterUtils") local beamUtils = require("utils/BeamUtils") +local attackBall = require("utils/AttackBall") local swarmUtils = require("SwarmUtils") package.path = "../libs/?.lua;" .. package.path local constants = require("Constants") @@ -22,7 +23,11 @@ local ELECTRIC_WORM_VARIATIONS = constants.ELECTRIC_WORM_VARIATIONS local buildUnitSpawner = swarmUtils.buildUnitSpawner local buildWorm = swarmUtils.buildWorm local createElectricAttack = biterUtils.createElectricAttack +local createAttackBall = attackBall.createAttackBall +local makeLaser = beamUtils.makeLaser +local createStreamAttack = biterUtils.createStreamAttack local makeBeam = beamUtils.makeBeam +local makeBubble = beamUtils.makeBubble local makeUnitAlienLootTable = biterUtils.makeUnitAlienLootTable local makeSpawnerAlienLootTable = biterUtils.makeSpawnerAlienLootTable @@ -32,6 +37,10 @@ local biterLoot = makeUnitAlienLootTable("blue") local spawnerLoot = makeSpawnerAlienLootTable("blue") local wormLoot = makeWormAlienLootTable("blue") +local electricBubble = makeBubble({ + name = "electric-worm", + lTint = {r=0, g=0.1, b=1, a=1} +}) -- electric biters @@ -346,16 +355,16 @@ buildUnitSpawner( { type = "attack", name = "range", - [1] = 7, - [2] = 7, - [3] = 8, - [4] = 8, - [5] = 9, - [6] = 9, - [7] = 10, - [8] = 10, - [9] = 11, - [10] = 11 + [1] = 11, + [2] = 11, + [3] = 12, + [4] = 12, + [5] = 13, + [6] = 13, + [7] = 14, + [8] = 14, + [9] = 15, + [10] = 15 } }, @@ -622,7 +631,33 @@ buildWorm( loot = wormLoot, attributes = {}, attack = { - damageType = "electric" + bubble = electricBubble, + damageType = "electric", + pointEffects = function(attributes) + return + { + { + type="nested-result", + action = { + { + type = "cluster", + cluster_count = attributes.clusters, + distance = attributes.clusterDistance, + distance_deviation = 3, + action_delivery = + { + type = "projectile", + projectile = attributes.laserName, + duration = 20, + direction_deviation = 0.6, + starting_speed = attributes.startingSpeed, + starting_speed_deviation = 0.3 + } + } + }, + } + } + end }, resistances = {}, @@ -639,10 +674,58 @@ buildWorm( [10] = 1.4 }, attackName = "worm-electric", - tint = {r=0, g=0.25, b=0.83, a=0.65} + tint = {r=0, g=0.25, b=0.83, a=0.65}, + pTint = {r=0, g=0.1, b=1, a=1}, + sTint = {r=0, g=0.1, b=1, a=1}, + lTint = {r=0, g=0.1, b=1, a=1} }, { + { + type = "attack", + name = "startingSpeed", + [1] = 0.25, + [2] = 0.25, + [3] = 0.27, + [4] = 0.27, + [5] = 0.29, + [6] = 0.29, + [7] = 0.31, + [8] = 0.31, + [9] = 0.33, + [10] = 0.33 + }, + + { + type = "attack", + name = "clusterDistance", + [1] = 3, + [2] = 3, + [3] = 4, + [4] = 4, + [5] = 5, + [6] = 5, + [7] = 6, + [8] = 6, + [9] = 7, + [10] = 7 + }, + + { + type = "attack", + name = "clusters", + [1] = 5, + [2] = 5, + [3] = 6, + [4] = 6, + [5] = 7, + [6] = 7, + [7] = 8, + [8] = 8, + [9] = 9, + [10] = 9 + }, + { type = "attribute", name = "health", @@ -882,54 +965,26 @@ buildWorm( [10] = 32 }, - { - type = "attack", - name = "width", - [1] = 0.5, - [2] = 0.5, - [3] = 0.6, - [4] = 0.6, - [5] = 0.7, - [6] = 0.7, - [7] = 0.8, - [8] = 0.8, - [9] = 0.9, - [10] = 0.9 - }, - - { - type = "attack", - name = "damageInterval", - [1] = 20, - [2] = 20, - [3] = 21, - [4] = 21, - [5] = 22, - [6] = 22, - [7] = 23, - [8] = 23, - [9] = 24, - [10] = 24 - }, - { type = "attack", - name = "duration", - [1] = 20, - [2] = 20, - [3] = 21, - [4] = 21, - [5] = 22, - [6] = 22, - [7] = 23, - [8] = 23, - [9] = 24, - [10] = 24 + name = "radius", + [1] = 1.5, + [2] = 1.6, + [3] = 1.7, + [4] = 1.8, + [5] = 1.9, + [6] = 2.0, + [7] = 2.2, + [8] = 2.3, + [9] = 2.5, + [10] = 3.0 } }, function (attributes) - return createElectricAttack(attributes, makeBeam(attributes)) + attributes.laserName = makeLaser(attributes) + return createStreamAttack(attributes, + createAttackBall(attributes)) end, ELECTRIC_WORM_VARIATIONS, diff --git a/prototypes/SwarmUtils.lua b/prototypes/SwarmUtils.lua index ceab38e..75019cf 100755 --- a/prototypes/SwarmUtils.lua +++ b/prototypes/SwarmUtils.lua @@ -238,6 +238,9 @@ local function generateApperance(unit, tier) if unit.pTint then unit.attack.pTint = calculateRGBa(unit.pTint, tier) end + if unit.lTint then + unit.attack.lTint = calculateRGBa(unit.lTint, tier) + end if unit.sTint then unit.attack.sTint = calculateRGBa(unit.sTint, tier) end diff --git a/prototypes/utils/AttackBall.lua b/prototypes/utils/AttackBall.lua index dff8aa8..732a11b 100755 --- a/prototypes/utils/AttackBall.lua +++ b/prototypes/utils/AttackBall.lua @@ -20,7 +20,7 @@ function AttackBall.createAttackBall(attributes) type = "area", radius = attributes.radius, force = (DISALLOW_FRIENDLY_FIRE and "enemy") or nil, - action_delivery = + action_delivery = (attributes.areaActionDelivery and attributes.areaActionDelivery(attributes)) or { { type = "instant", diff --git a/prototypes/utils/BeamUtils.lua b/prototypes/utils/BeamUtils.lua index 92eef79..ee4b4e7 100755 --- a/prototypes/utils/BeamUtils.lua +++ b/prototypes/utils/BeamUtils.lua @@ -1,150 +1,219 @@ local beamUtils = {} +function beamUtils.makeBubble(attributes) + local name = attributes.name .. "-bubble-rampant" + data:extend({{ + type = "explosion", + name = name, + flags = {"not-on-map"}, + animation_speed = 1, + animations = + { + { + filename = "__base__/graphics/entity/laser-bubble/laser-bubble.png", + priority = "extra-high", + width = 8, + height = 8, + frame_count = 5 + } + }, + light = {intensity = 1, size = 10, color = attributes.lTint or {r = 1.0, g = 1.0, b = 1.0}}, + smoke = "smoke-fast", + smoke_count = 2, + smoke_slow_down_factor = 1 + }}) + return name +end + +function beamUtils.makeLaser(attributes) + local name = attributes.name .. "-laser-rampant" + data:extend({{ + type = "projectile", + name = name , + flags = {"not-on-map"}, + collision_box = attributes.collisionBox or {{-0.3, -1.1}, {0.3, 1.1}}, + acceleration = attributes.acceleration or 0.03, + action = + { + type = "direct", + action_delivery = + { + type = "instant", + target_effects = + { + { + type = "create-entity", + entity_name = attributes.bubble or "laser-bubble" + }, + { + type = "damage", + damage = { amount = attributes.damage or 5, type = attributes.damageType or "laser"} + } + } + } + }, + light = {intensity = 0.5, size = 10}, + animation = + { + filename = "__base__/graphics/entity/laser/laser-to-tint-medium.png", + tint = attributes.lTint or {r=1.0, g=0.0, b=0.0}, + frame_count = 1, + width = 12, + height = 33, + priority = "high", + blend_mode = "additive" + }, + speed = 0.15 + }}) + return name +end + function beamUtils.makeBeam(attributes) - local result = - { - type = "beam", - flags = {"not-on-map"}, - width = attributes.width or 0.5, - damage_interval = attributes.damageInterval or 20, - action = - { - type = "direct", - action_delivery = - { - type = "instant", - target_effects = - { - { - type = "damage", - damage = { amount = attributes.damage or 10, type = attributes.damageType or "electric"} - } - } - } - }, - start = - { - filename = "__base__/graphics/entity/beam/tileable-beam-START.png", - line_length = 4, - width = 52, - height = 40, - frame_count = 16, - axially_symmetrical = false, - direction_count = 1, - shift = {-0.03125, 0}, - hr_version = { - filename = "__base__/graphics/entity/beam/hr-tileable-beam-START.png", - line_length = 4, - width = 94, - height = 66, - frame_count = 16, - axially_symmetrical = false, - direction_count = 1, - shift = {0.53125, 0}, - scale = 0.5, - } - }, - ending = - { - filename = "__base__/graphics/entity/beam/tileable-beam-END.png", - line_length = 4, - width = 49, - height = 54, - frame_count = 16, - axially_symmetrical = false, - direction_count = 1, - shift = {-0.046875, 0}, - hr_version = { - filename = "__base__/graphics/entity/beam/hr-tileable-beam-END.png", - line_length = 4, - width = 91, - height = 93, - frame_count = 16, - axially_symmetrical = false, - direction_count = 1, - shift = {-0.078125, -0.046875}, - scale = 0.5, - } - }, - head = - { - filename = "__base__/graphics/entity/beam/beam-head.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - animation_speed = 0.5, - blend_mode = "additive-soft", - }, - tail = - { - filename = "__base__/graphics/entity/beam/beam-tail.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - blend_mode = "additive-soft", - }, - body = - { - { - filename = "__base__/graphics/entity/beam/beam-body-1.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - blend_mode = "additive-soft", - }, - { - filename = "__base__/graphics/entity/beam/beam-body-2.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - blend_mode = "additive-soft", - }, - { - filename = "__base__/graphics/entity/beam/beam-body-3.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - blend_mode = "additive-soft", - }, - { - filename = "__base__/graphics/entity/beam/beam-body-4.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - blend_mode = "additive-soft", - }, - { - filename = "__base__/graphics/entity/beam/beam-body-5.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - blend_mode = "additive-soft", - }, - { - filename = "__base__/graphics/entity/beam/beam-body-6.png", - line_length = 16, - width = 45, - height = 39, - frame_count = 16, - blend_mode = "additive-soft", - }, - } - } + local result = + { + type = "beam", + flags = {"not-on-map"}, + width = attributes.width or 0.5, + collision_box = attributes.collisionBox or {{-0.3, -1.1}, {0.3, 1.1}}, + damage_interval = attributes.damageInterval or 20, + action = + { + type = "direct", + action_delivery = + { + type = "instant", + target_effects = + { + { + type = "damage", + damage = { amount = attributes.damage or 10, type = attributes.damageType or "electric"} + } + } + } + }, + start = + { + filename = "__base__/graphics/entity/beam/tileable-beam-START.png", + line_length = 4, + width = 52, + height = 40, + frame_count = 16, + axially_symmetrical = false, + direction_count = 1, + shift = {-0.03125, 0}, + hr_version = { + filename = "__base__/graphics/entity/beam/hr-tileable-beam-START.png", + line_length = 4, + width = 94, + height = 66, + frame_count = 16, + axially_symmetrical = false, + direction_count = 1, + shift = {0.53125, 0}, + scale = 0.5, + } + }, + ending = + { + filename = "__base__/graphics/entity/beam/tileable-beam-END.png", + line_length = 4, + width = 49, + height = 54, + frame_count = 16, + axially_symmetrical = false, + direction_count = 1, + shift = {-0.046875, 0}, + hr_version = { + filename = "__base__/graphics/entity/beam/hr-tileable-beam-END.png", + line_length = 4, + width = 91, + height = 93, + frame_count = 16, + axially_symmetrical = false, + direction_count = 1, + shift = {-0.078125, -0.046875}, + scale = 0.5, + } + }, + head = + { + filename = "__base__/graphics/entity/beam/beam-head.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + animation_speed = 0.5, + blend_mode = "additive-soft", + }, + tail = + { + filename = "__base__/graphics/entity/beam/beam-tail.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + blend_mode = "additive-soft", + }, + body = + { + { + filename = "__base__/graphics/entity/beam/beam-body-1.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + blend_mode = "additive-soft", + }, + { + filename = "__base__/graphics/entity/beam/beam-body-2.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + blend_mode = "additive-soft", + }, + { + filename = "__base__/graphics/entity/beam/beam-body-3.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + blend_mode = "additive-soft", + }, + { + filename = "__base__/graphics/entity/beam/beam-body-4.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + blend_mode = "additive-soft", + }, + { + filename = "__base__/graphics/entity/beam/beam-body-5.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + blend_mode = "additive-soft", + }, + { + filename = "__base__/graphics/entity/beam/beam-body-6.png", + line_length = 16, + width = 45, + height = 39, + frame_count = 16, + blend_mode = "additive-soft", + }, + } + } result.working_sound = - { - { - filename = "__base__/sound/fight/electric-beam.ogg", - volume = 0.7 - } - } + { + { + filename = "__base__/sound/fight/electric-beam.ogg", + volume = 0.7 + } + } local name = attributes.name .. "-beam-rampant" result.name = name diff --git a/prototypes/utils/BiterUtils.lua b/prototypes/utils/BiterUtils.lua index d40cb07..c850629 100755 --- a/prototypes/utils/BiterUtils.lua +++ b/prototypes/utils/BiterUtils.lua @@ -609,20 +609,21 @@ function biterFunctions.createElectricAttack(attributes, electricBeam, animation type = "beam", ammo_category = "combat-robot-beam", cooldown = attributes.cooldown or 20, - range = attributes.range or 15, + min_attack_distance = (attributes.range and (attributes.range - 2)) or 15, + range = (attributes.range and (attributes.range + 2)) or 15, ammo_type = { category = "combat-robot-beam", action = { - type = "direct", + type = "line", + range = (attributes.range and (attributes.range + 2)) or 15, + width = attributes.width or 0.5, action_delivery = { type = "beam", beam = electricBeam or "electric-beam", - max_length = attributes.range or 15, - duration = attributes.duration or 20, - source_offset = {0.15, -0.5}, + duration = attributes.duration or 20 } } }, @@ -630,49 +631,30 @@ function biterFunctions.createElectricAttack(attributes, electricBeam, animation } end - -function biterFunctions.createRailAttack(attributes, railBeam, animation) +function biterFunctions.createCapsuleAttack(attributes, capsule, animation) return { - type = "projectile", - ammo_category = "railgun", - cooldown = 3 * 60, - movement_slow_down_factor = 0.6, - projectile_creation_distance = 0.6, - ammo_type = { - category = "railgun", - target_type = "direction", - clamp_position = true, - action = + type = "projectile", + ammo_category = "capsule", + cooldown = attributes.cooldown or 15, + projectile_creation_distance = 0.6, + range = attributes.range or 20, + ammo_type = { - type = "line", - range = 50, - width = attributes.width or 0.5, - - source_effects = + category = "capsule", + target_type = "position", + action = { - type = "create-explosion", - entity_name = railBeam or "railgun-beam" - }, - action_delivery = - { - type = "instant", - target_effects = + type = "direct", + action_delivery = { - type = "damage", - damage = { amount = attributes.damage or 100, type=attributes.damageType or "physical" } + type = "projectile", + projectile = capsule or "defender-capsule", + starting_speed = attributes.startingSpeed or 0.3, + max_range = attributes.maxRange or 20 } } - } - }, - animation = animation, - range = 50, - sound = - { - { - filename = "__base__/sound/railgun.ogg", - volume = 0.8 - } - } + }, + animation = animation } end diff --git a/prototypes/utils/DroneUtils.lua b/prototypes/utils/DroneUtils.lua new file mode 100755 index 0000000..a313f15 --- /dev/null +++ b/prototypes/utils/DroneUtils.lua @@ -0,0 +1,285 @@ +local droneUtils = {} + +function droneUtils.createDrone(attributes) + return { + type = "combat-robot", + name = "defender2", + icon = "__base__/graphics/icons/defender.png", + icon_size = 32, + flags = {"placeable-player", "player-creation", "placeable-off-grid", "not-on-map", "not-repairable"}, + resistances = { { type = "fire", percent = 95 } }, + subgroup="capsule", + order="e-a-a", + max_health = 60, + alert_when_damaged = false, + collision_box = {{0, 0}, {0, 0}}, + selection_box = {{-0.5, -1.5}, {0.5, -0.5}}, + distance_per_frame = 0.13, + time_to_live = 60 * 45, + follows_player = true, + friction = 0.01, + range_from_player = 6.0, + speed = 0.01, + destroy_action = + { + type = "direct", + action_delivery = + { + type = "instant", + source_effects = + { + type = "create-entity", + entity_name = "explosion" + } + } + }, + attack_parameters = + { + type = "projectile", + ammo_category = "bullet", + cooldown = 20, + projectile_center = {0, 1}, + projectile_creation_distance = 0.6, + range = 15, + sound = make_light_gunshot_sounds(), + ammo_type = + { + category = "bullet", + action = + { + type = "direct", + action_delivery = + { + type = "stream", + stream = "acid-ball-stream-rampant", + source_effects = + { + type = "create-explosion", + entity_name = "explosion-gunshot-small" + }, + target_effects = + { + { + type = "create-entity", + entity_name = "explosion-hit" + }, + { + type = "damage", + damage = { amount = 5 , type = "physical"} + } + } + } + } + } + }, + idle = + { + layers = + { + { + filename = "__base__/graphics/entity/defender-robot/defender-robot.png", + priority = "high", + line_length = 16, + width = 32, + height = 33, + frame_count = 1, + direction_count = 16, + shift = {0, 0.015625}, + hr_version = { + filename = "__base__/graphics/entity/defender-robot/hr-defender-robot.png", + priority = "high", + line_length = 16, + width = 56, + height = 59, + frame_count = 1, + direction_count = 16, + shift = util.by_pixel(0, 0.25), + scale = 0.5 + } + }, + { + filename = "__base__/graphics/entity/defender-robot/defender-robot-mask.png", + priority = "high", + line_length = 16, + width = 18, + height = 16, + frame_count = 1, + direction_count = 16, + shift = {0, -0.125}, + apply_runtime_tint = true, + hr_version = { + filename = "__base__/graphics/entity/defender-robot/hr-defender-robot-mask.png", + priority = "high", + line_length = 16, + width = 28, + height = 21, + frame_count = 1, + direction_count = 16, + shift = util.by_pixel(0, -4.75), + apply_runtime_tint = true, + scale = 0.5 + } + }, + } + }, + shadow_idle = + { + filename = "__base__/graphics/entity/defender-robot/defender-robot-shadow.png", + priority = "high", + line_length = 16, + width = 43, + height = 23, + frame_count = 1, + direction_count = 16, + shift = {0.859375, 0.609375}, + hr_version = { + filename = "__base__/graphics/entity/defender-robot/hr-defender-robot-shadow.png", + priority = "high", + line_length = 16, + width = 88, + height = 50, + frame_count = 1, + direction_count = 16, + shift = util.by_pixel(25.5, 19), + scale = 0.5 + } + }, + in_motion = + { + layers = + { + { + filename = "__base__/graphics/entity/defender-robot/defender-robot.png", + priority = "high", + line_length = 16, + width = 32, + height = 33, + frame_count = 1, + direction_count = 16, + shift = {0, 0.015625}, + y = 33, + hr_version = { + filename = "__base__/graphics/entity/defender-robot/hr-defender-robot.png", + priority = "high", + line_length = 16, + width = 56, + height = 59, + frame_count = 1, + direction_count = 16, + shift = util.by_pixel(0, 0.25), + y = 59, + scale = 0.5 + } + }, + { + filename = "__base__/graphics/entity/defender-robot/defender-robot-mask.png", + priority = "high", + line_length = 16, + width = 18, + height = 16, + frame_count = 1, + direction_count = 16, + shift = {0, -0.125}, + apply_runtime_tint = true, + y = 16, + hr_version = { + filename = "__base__/graphics/entity/defender-robot/hr-defender-robot-mask.png", + priority = "high", + line_length = 16, + width = 28, + height = 21, + frame_count = 1, + direction_count = 16, + shift = util.by_pixel(0, -4.75), + apply_runtime_tint = true, + y = 21, + scale = 0.5 + } + }, + } + }, + shadow_in_motion = + { + filename = "__base__/graphics/entity/defender-robot/defender-robot-shadow.png", + priority = "high", + line_length = 16, + width = 43, + height = 23, + frame_count = 1, + direction_count = 16, + shift = {0.859375, 0.609375}, + hr_version = { + filename = "__base__/graphics/entity/defender-robot/hr-defender-robot-shadow.png", + priority = "high", + line_length = 16, + width = 88, + height = 50, + frame_count = 1, + direction_count = 16, + shift = util.by_pixel(25.5, 19), + scale = 0.5 + } + } + } +end + +function droneUtils.createCapsuleProjectile(attributes) + return { + type = "projectile", + name = "defender2-capsule", + flags = {"not-on-map"}, + direction_only = true, + acceleration = 0.005, + action = + { + type = "direct", + action_delivery = + { + type = "instant", + target_effects = + { + { + type = "create-entity", + show_in_tooltip = true, + entity_name = "defender2", + }, + } + } + }, + light = {intensity = 0.5, size = 4}, + enable_drawing_with_mask = true, + animation = { + layers = { + { + filename = "__base__/graphics/entity/combat-robot-capsule/defender-capsule.png", + flags = { "no-crop" }, + frame_count = 1, + width = 28, + height = 20, + priority = "high" + }, + { + filename = "__base__/graphics/entity/combat-robot-capsule/defender-capsule-mask.png", + flags = { "no-crop" }, + frame_count = 1, + width = 28, + height = 20, + priority = "high", + apply_runtime_tint = true, + }, + }, + }, + shadow = + { + filename = "__base__/graphics/entity/combat-robot-capsule/defender-capsule-shadow.png", + flags = { "no-crop" }, + frame_count = 1, + width = 26, + height = 20, + priority = "high" + }, + smoke = capsule_smoke + } +end + +return droneUtils