Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 42 additions & 8 deletions library/lua/script-manager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,28 +88,60 @@ local INSTALLED_MODS_PATH = 'data/installed_mods/'
-- changes to the files)
local MOD_PATH_ROOTS = {WORKSHOP_MODS_PATH, MODS_PATH, INSTALLED_MODS_PATH}

local function get_mod_id_and_version(path)
local function get_mod_info(path)
local idfile = path .. '/info.txt'
local ok, lines = pcall(io.lines, idfile)
if not ok then return end
local id, version
local id, numerical_version, name, steam_id, display_version
for line in lines do
if not id then
_,_,id = line:find('^%[ID:([^%]]+)%]')
end
if not version then
if not numerical_version then
-- note this doesn't include the closing brace since some people put
-- non-number characters in here, and DF only reads the leading digits
-- as the numeric version
_,_,version = line:find('^%[NUMERIC_VERSION:(%d+)')
_,_,numerical_version = line:find('^%[NUMERIC_VERSION:(%d+)')
end
if not display_version then
if line:find('^%[DISPLAYED_VERSION:') then display_version = line:sub(20,-2) end
end
if not name then
_,_,name = line:find('^%[NAME:([^%]]+)%]')
end
if not steam_id then
_,_,steam_id = line:find('^%[STEAM_FILE_ID:(%d+)')
end

-- note that we do *not* want to break out of this loop early since
-- lines has to hit EOF to close the file
end
return id, version
return {
id=id,
numerical_version=numerical_version,
name=name,
steam_id=steam_id,
display_version=display_version,
}
end

function getAllModsInfo(include_vanilla, mods, mod_paths)
for _,path in ipairs(df.global.world.object_loader.object_load_order_src_dir) do
path = tostring(path.value)
if not include_vanilla then
-- skip vanilla "mods"
if not path:startswith(INSTALLED_MODS_PATH) then goto continue end
end
local info = get_mod_info(path)
if info == nil then goto continue end
if not info.id or not info.numerical_version then goto continue end
mods[info.id]= {handled=true, name=info.name, version=info.display_version, steam_id=info.steam_id}
add_mod_paths(mod_paths, info.id, path, '.')
::continue::
end
end

local function add_mod_paths(mod_paths, id, base_path, subdir)
function add_mod_paths(mod_paths, id, base_path, subdir)
local sep = base_path:endswith('/') and '' or '/'
local path = ('%s%s%s'):format(base_path, sep, subdir)
if dfhack.filesystem.isdir(path) then
Expand All @@ -128,7 +160,7 @@ function get_mod_paths(installed_subdir, active_subdir)
path = tostring(path.value)
-- skip vanilla "mods"
if not path:startswith(INSTALLED_MODS_PATH) then goto continue end
local id = get_mod_id_and_version(path)
local id = get_mod_info(path).id
if not id then goto continue end
mods[id] = {handled=true}
if active_subdir then
Expand All @@ -145,7 +177,9 @@ function get_mod_paths(installed_subdir, active_subdir)
if not files then goto skip_path_root end
for _,f in ipairs(files) do
if not f.isdir then goto continue end
local id, version = get_mod_id_and_version(f.path)
local info = get_mod_info(f.path)
if info == nil then goto continue end
local id, version = info.id,info.numerical_version
if not id or not version then goto continue end
local mod = ensure_key(mods, id)
if mod.handled then goto continue end
Expand Down
15 changes: 13 additions & 2 deletions plugins/spectate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static uint32_t next_cycle_unpaused_ms = 0; // threshold for the next cycle
static const size_t MAX_HISTORY = 200;

static const float CITIZEN_COMBAT_PREFERRED_WEIGHT = 25.0f;
static const float NICKNAMED_CITIZEN_PREFERRED_WEIGHT = 15.0f;
static const float OTHER_COMBAT_PREFERRED_WEIGHT = 10.0f;
static const float JOB_WEIGHT = 5.0f;
static const float OTHER_WEIGHT = 1.0f;
Expand Down Expand Up @@ -71,6 +72,7 @@ static struct Configuration {
bool include_wildlife;
bool prefer_conflict;
bool prefer_new_arrivals;
bool prefer_nicknamed;
int32_t follow_ms;

void reset() {
Expand All @@ -82,6 +84,7 @@ static struct Configuration {
include_wildlife = false;
prefer_conflict = true;
prefer_new_arrivals = true;
prefer_nicknamed = true;
follow_ms = 10000;
}
} config;
Expand Down Expand Up @@ -436,6 +439,7 @@ static bool is_in_combat(df::unit *unit) {
static void get_dwarf_buckets(color_ostream &out,
vector<df::unit*> &citizen_combat_units,
vector<df::unit*> &other_combat_units,
vector<df::unit*> &nicknamed_units,
vector<df::unit*> &job_units,
vector<df::unit*> &other_units)
{
Expand All @@ -452,11 +456,13 @@ static void get_dwarf_buckets(color_ostream &out,
continue;

if (is_in_combat(unit)) {
TRACE(cycle,out).print("unit %d is in combat: %s\n", unit->id, DF2CONSOLE(Units::getReadableName(unit)).c_str());
TRACE(cycle, out).print("unit %d is in combat: %s\n", unit->id, DF2CONSOLE(Units::getReadableName(unit)).c_str());
if (Units::isCitizen(unit, true) || Units::isResident(unit, true))
citizen_combat_units.push_back(unit);
else
other_combat_units.push_back(unit);
} else if (!unit->name.nickname.empty()) {
nicknamed_units.push_back(unit);
} else if (unit->job.current_job && !boring_jobs.contains(unit->job.current_job->job_type)) {
job_units.push_back(unit);
} else {
Expand Down Expand Up @@ -510,9 +516,10 @@ static void follow_a_dwarf(color_ostream &out) {

vector<df::unit*> citizen_combat_units;
vector<df::unit*> other_combat_units;
vector<df::unit*> nicknamed_units;
vector<df::unit*> job_units;
vector<df::unit*> other_units;
get_dwarf_buckets(out, citizen_combat_units, other_combat_units, job_units, other_units);
get_dwarf_buckets(out, citizen_combat_units, other_combat_units, nicknamed_units, job_units, other_units);

set_next_cycle_unpaused_ms(out, !citizen_combat_units.empty());

Expand All @@ -523,6 +530,7 @@ static void follow_a_dwarf(color_ostream &out) {
intervals.push_back(0);
add_bucket(citizen_combat_units, units, intervals, weights, config.prefer_conflict ? CITIZEN_COMBAT_PREFERRED_WEIGHT : JOB_WEIGHT);
add_bucket(other_combat_units, units, intervals, weights, config.prefer_conflict ? OTHER_COMBAT_PREFERRED_WEIGHT : JOB_WEIGHT);
add_bucket(nicknamed_units, units, intervals, weights, config.prefer_nicknamed ? NICKNAMED_CITIZEN_PREFERRED_WEIGHT : OTHER_WEIGHT);
add_bucket(job_units, units, intervals, weights, JOB_WEIGHT);
add_bucket(other_units, units, intervals, weights, OTHER_WEIGHT);

Expand All @@ -538,6 +546,7 @@ static void follow_a_dwarf(color_ostream &out) {
if (debug_cycle.isEnabled(DebugCategory::LDEBUG)) {
DUMP_BUCKET(citizen_combat_units);
DUMP_BUCKET(other_combat_units);
DUMP_BUCKET(nicknamed_units);
DUMP_BUCKET(job_units);
DUMP_BUCKET(other_units);
DUMP_FLOAT_VECTOR(intervals);
Expand Down Expand Up @@ -575,6 +584,8 @@ static void spectate_setSetting(color_ostream &out, string name, int val) {
config.prefer_conflict = val;
} else if (name == "prefer-new-arrivals") {
config.prefer_new_arrivals = val;
} else if (name == "prefer-nicknamed") {
config.prefer_nicknamed = val;
} else if (name == "follow-seconds") {
if (val <= 0) {
WARN(control,out).print("follow-seconds must be a positive integer\n");
Expand Down
Loading