Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embark Anyone #1260

Merged
merged 12 commits into from
Aug 9, 2024
23 changes: 23 additions & 0 deletions docs/embark-anyone.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
embark-anyone
=============

.. dfhack-tool::
:summary: Allows you to embark as any civilisation, including dead and non-dwarven ones.
:tags: embark armok

This script can be ran on the embark screen and presents a list of civilisations that
are not normally playable to add to the "Select Origin Civ" menu. This includes dead
civilisations, the normal non-dwarven civilisations, and subterranean animal people.
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved


myk002 marked this conversation as resolved.
Show resolved Hide resolved
Usage
-----

::

embark-anyone

Note
-----
Non-dwarven civs have their own mechanics which can render fortress mode difficult
to unplayable. Preparing carefully is advised, and some crucial items may need to be spawned in.
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved
117 changes: 117 additions & 0 deletions embark-anyone.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
local dialogs = require 'gui.dialogs'
local utils = require 'utils'
local choices = {}
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved

function addCivToEmbarkList(info)
local viewscreen = dfhack.gui.getDFViewscreen(true)

viewscreen.start_civ:insert ('#', info.civ)
viewscreen.start_civ_nem_num:insert ('#', info.nemeses)
viewscreen.start_civ_entpop_num:insert ('#', info.pops)
viewscreen.start_civ_site_num:insert ('#', info.sites)
end

function embarkAnyone()
local viewscreen = dfhack.gui.getDFViewscreen(true)
local existing_civs = {}
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved

for _,existing_civ in ipairs(viewscreen.start_civ) do
existing_civs[existing_civ.id] = true
end

if viewscreen._type ~= df.viewscreen_choose_start_sitest then
qerror("This script can only be used on the embark screen!")
end

for i, civ in ipairs (df.global.world.entities.all) do
-- Test if entity is a civ
if civ.type ~= df.historical_entity_type.Civilization then goto continue end
-- Test if entity is already in embark list
if existing_civs[civ.id] then goto continue end

local sites = 0
local pops = 0
local nemeses = 0
local histfigs = 0
local label = ''

-- Civs keep links to sites they no longer hold, so check owner
-- We also take the opportunity to count population
for j, link in ipairs(civ.site_links) do
local site = df.world_site.find(link.target)
if site ~= nil and site.civ_id == civ.id then
sites = sites + 1

-- DF stores population info as an array of groups of residents (?).
-- Inspecting these further could give a more accurate count.
for _, group in ipairs(site.populace.inhabitants) do
pops = pops + group.count
end
end

-- Count living nemeses
for _, nem_id in ipairs (civ.nemesis_ids) do
local nem = df.nemesis_record.find(nem_id)
if nem ~= nil and nem.figure.died_year == -1 then
nemeses = nemeses + 1
end
end

-- Count living histfigs
-- Used for death detection. May be redundant.
for _, fig_id in ipairs (civ.histfig_ids) do
local fig = df.historical_figure.find(fig_id)
if fig ~= nil and fig.died_year == -1 then
histfigs = histfigs + 1
end
end
end

-- Find the civ's name, or come up with one
if civ.name.has_name then
label = dfhack.TranslateName(civ.name, true) .. "\n"
else
label = "Unnamed " ..
dfhack.units.getRaceReadableNameById(civ.race) ..
" civilisation\n"
end

-- Add species
label = label .. dfhack.units.getRaceNamePluralById(civ.race) .. "\n"

-- Add pop & site count or mark civ as dead.
if histfigs == 0 and pops == 0 then
label = label .. "Dead"
else
label = label .. "Pop: " .. (pops + nemeses) .. " Sites: " .. sites
end

table.insert(choices, {text = label, search_key = label:lower(),
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved
info = {civ = civ, pops = pops, sites = sites,
nemeses = nemeses}})

::continue::
end

if #choices then
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved
dialogs.ListBox{
frame_title = 'Embark Anyone',
text = 'Select a civilisation to add to the list of origin civs:',
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved
text_pen = COLOR_WHITE,
choices = choices,
on_select = function(id, choice)
addCivToEmbarkList(choice.info)
end,
with_filter = true,
row_height = 4,
}:show()
else
dialogs.MessageBox{
frame_title = 'Embark Anyone',
text = 'No additional civilisations found.'
ProtonNumber marked this conversation as resolved.
Show resolved Hide resolved
}:show()
end

end

embarkAnyone()
Loading