cs / factorio /data /core /lualib /crash-site.lua
enemy7's picture
Upload 1553 files
898c672
raw
history blame
9.58 kB
local util = require("util")
local main_ship_name = "crash-site-spaceship"
local default_ship_parts = function()
return
{
{
name = "crash-site-spaceship-wreck-big-1",
angle_deviation = 0.1,
max_distance = 25,
min_separation = 2,
fire_count = 1
},
{
name = "crash-site-spaceship-wreck-big-2",
angle_deviation = 0.1,
max_distance = 25,
min_separation = 2,
explosion_count = 3,
fire_count = 1
},
{
name = "crash-site-spaceship-wreck-medium",
variations = 3,
angle_deviation = 0.05,
max_distance = 30,
min_separation = 1,
explosion_count = 1,
fire_count = 1
},
{
name = "crash-site-spaceship-wreck-small",
variations = 6,
angle_deviation = 0.05,
min_separation = 1,
fire_count = 1
},
{
name = "crash-site-fire-smoke",
angle_deviation = 0.08,
repeat_count = 0,
scale_lifetime = true
}
}
end
local rotate = function(offset, angle)
local x = offset[1]
local y = offset[2]
local rotated_x = x * math.cos(angle) - y * math.sin(angle)
local rotated_y = x * math.sin(angle) + y * math.cos(angle)
return {rotated_x, rotated_y}
end
local entry_angle = 0.70
local random = math.random
local get_offset = function(part)
local angle = entry_angle + ((random() - 0.5) * part.angle_deviation)
angle = angle - 0.25
angle = angle * math.pi * 2
local distance = 8 + (random() * (part.max_distance or 40))
local offset = rotate({distance, 0}, angle)
return offset
end
local get_name = function(part, k)
if not part.variations then return part.name end
local variant = k or random(part.variations)
return part.name.."-"..variant
end
local get_lifetime = function(offset)
--Generally, close to the ship, last longer.
local distance = ((offset[1] * offset[1]) + (offset[2] * offset[2])) ^ 0.5
local time = random(60 * 20, 60 * 30) - math.min(distance * 100, 15 * 60)
return time
end
local get_random_position = function(box, x_scale, y_scale)
local x_scale = x_scale or 1
local y_scale = y_scale or 1
local x1 = box.left_top.x
local y1 = box.left_top.y
local x2 = box.right_bottom.x
local y2 = box.right_bottom.y
local x = ((x2 - x1) * x_scale * (random() - 0.5)) + ((x1 + x2) / 2)
local y = ((y2 - y1) * y_scale * (random() - 0.5)) + ((y1 + y2) / 2)
return {x, y}
end
local random_from_map = function(map)
local array = {}
local i = 1
for k, v in pairs (map) do
array[i] = k
i = i + 1
end
local key = array[random(#array)]
local value = map[key]
return key, value
end
local insert_items_randomly = function(entities, items)
local item_prototypes = game.item_prototypes
for name, count in pairs (items) do
if not item_prototypes[name] then
items[name] = nil
end
end
if not next(items) then return end
for unit_number, entity in pairs (entities) do
if not entity.valid then
entities[unit_number] = nil
end
end
if not next(entities) then return end
local stupid = 1000
while true do
local item_name, count = random_from_map(items)
local unit_number, entity = random_from_map(entities)
local inserted = entity.insert{name = item_name, count = 1}
if inserted == count then
items[item_name] = nil
else
items[item_name] = count - inserted
end
if not next(items) then break end
stupid = stupid - 1
if stupid <= 0 then break end
end
end
local main_ship_flame_count = 4
local main_ship_explosion_count = 10
local lib = {}
lib.create_crash_site = function(surface, position, ship_items, part_items, ship_parts)
local main_ship = surface.create_entity
{
name = main_ship_name,
position = position,
force = "player",
create_build_effect_smoke = false
}
util.insert_safe(main_ship, ship_items)
local box = main_ship.bounding_box
for k, entity in pairs (surface.find_entities_filtered{area = box, force = "neutral", collision_mask = "player-layer"}) do
if entity.valid then
if entity.type == "tree" then
entity.die()
else
entity.destroy()
end
end
end
for k = 1, main_ship_flame_count do
local position = get_random_position(box, 0.8, 0.5)
surface.create_entity
{
name = "crash-site-fire-flame",
position = position
}
local fire = surface.create_entity
{
name = "crash-site-fire-smoke",
position = position
}
fire.time_to_live = random(60 * 15, 60 * 30)
fire.time_to_next_effect = random(60 * 3)
end
for k = 1, main_ship_explosion_count do
local explosions = surface.create_entity
{
name = "crash-site-explosion-smoke",
position = get_random_position(box, 0.8, 0.5)
}
explosions.time_to_live = random(60 * 15, 60 * 30)
explosions.time_to_next_effect = random(60)
end
local wreck_parts = {}
for k, part in pairs(ship_parts or default_ship_parts()) do
for k = 1, (part.variations or 1) do
local name = get_name(part, k)
for i = 1, part.repeat_count or 1 do
local part_position
local count = 0
local offset
while true do
offset = get_offset(part)
local x = (position[1] or position.x) + offset[1]
local y = (position[2] or position.y) + offset[2]
part_position = {x, y}
local can_place = surface.can_place_entity
{
name = name,
position = part_position,
force = "player",
build_check_type = defines.build_check_type.manual_ghost,
forced = true
}
if can_place then
if not part.min_separation or surface.count_entities_filtered{position = part_position, radius = part.min_separation, limit = 1, type = "tree", invert = true} == 0 then
break
end
end
count = count + 1
if count > 20 then
part_position = surface.find_non_colliding_position(name, part_position, 50, 4)
break
end
end
if part_position then
local entity = surface.create_entity
{
name = name,
position = part_position,
force = part.force or "neutral",
create_build_effect_smoke = false
}
if entity.get_output_inventory() and #entity.get_output_inventory() > 0 then
wreck_parts[entity.unit_number] = entity
end
for k, entity in pairs (surface.find_entities_filtered{type = {"tree", "simple-entity"}, position = part_position, radius = 1 + entity.get_radius()}) do
if entity.type == "tree" then
entity.die()
else
entity.destroy()
end
end
if part.explosion_count then
for k = 1, part.explosion_count do
local explosions = surface.create_entity
{
name = "crash-site-explosion-smoke",
position = get_random_position(entity.bounding_box)
}
explosions.time_to_live = get_lifetime(offset)
explosions.time_to_next_effect = random(30)
end
end
if part.fire_count then
for k = 1, part.fire_count do
surface.create_entity
{
name = "crash-site-fire-flame",
position = get_random_position(entity.bounding_box)
}
local explosions = surface.create_entity
{
name = "crash-site-fire-smoke",
position = get_random_position(entity.bounding_box)
}
explosions.time_to_live = get_lifetime(offset)
explosions.time_to_next_effect = random(30)
end
end
if part.scale_lifetime then
entity.time_to_live = get_lifetime(offset)
entity.time_to_next_effect = random(60)
end
end
end
end
end
insert_items_randomly(wreck_parts, part_items)
end
local set_label_size = function(player)
local label = player.gui.screen.skip_cutscene_label
if not label then return end
label.style.horizontal_align = "center"
local resolution = player.display_resolution
label.style.width = resolution.width / player.display_scale
label.location = {0, (resolution.height) - ((20 + 8) * player.display_scale)}
end
lib.create_cutscene = function(player, goal_position)
local offset = rotate({60, 0}, (entry_angle - 0.25) * math.pi * 2)
local start_position = {goal_position[1] + offset[1], goal_position[2] + offset[2]}
player.set_controller
{
type = defines.controllers.cutscene,
waypoints =
{
{
position = goal_position,
transition_time = 450,
zoom = 2,
time_to_wait = 150
},
{
target = player.character,
transition_time = 150,
zoom = 1.5,
time_to_wait = 0
}
},
start_position = start_position,
start_zoom = 2
}
local label = player.gui.screen.add{type = "label", caption = {"skip-cutscene"}, name = "skip_cutscene_label"}
set_label_size(player)
end
lib.is_crash_site_cutscene = function(event)
return event.player_index == 1 and event.waypoint_index == 1
end
lib.on_player_display_refresh = function(event)
local player = game.get_player(event.player_index)
set_label_size(player)
end
lib.default_ship_parts = default_ship_parts
return lib