df-structures
df-structures copied to clipboard
creature.flags unk_6e, unk_6f & unk_49
only humans have unk_6f.
the set of creatures that have either unk_6e or unk_49 is exactly the set of creatures armor can be made for via the blacksmith. notably this set of creatures does not include several species that can equip and learn/speak/utter, like ogres, trolls, gremlins, gnomes, foul blendecs, troglodytes etc.
only animal men and gorlaks have unk_6e, 187 species in total. 14 species have unk_49, among them dwarves, elves, humans, goblins and kobolds. the rest are animal men as well, some of which have unk_6e too, but not all.
specifically, bat men, olm men, cave fish men, cave swallow men have both flags. amphib men, ant men, reptile men, rodent men and serpent men have unk_49, but not unk_6e.
presumably these species either have entities or are advmode controllable?
only humans have unk_6f.
[OUTSIDER_CONTROLLABLE]?
A thought - It could be "large" clothing? as that is often a modifier of human and above sized clothing. A troll can slip into a polar bear man sized suit of armor made from goblin smiths in dwarf fortress mode in play and as defined by the player quite comfortably, but their own clothes sized for them (goblin civilisation can embark with pre-clothed trolls for reference) will be "Large xobjectx it is sized for trolls" on description.
unk_49 reasonably must correspond to 'small' if you look at it in perspective of a larger animal (dwarf downward in height where it usually starts), while unk_6f must be large. starting roughly at human size (and because of the range of variable intelligent animal men in size compared to unintelligent generic races and only playable with modding trolls this probably plays a factor) even if this isn't precisely correct it should help steer you towards a better answer.
If you give trolls hero production or outsider controllable it wouldn't change their conditions of being excluded from the list (though a careful observation might be to see if their clothes are still listed as 'large') therefore i can't personally see the definite connection between the two.
unk_6e seems to correspond to LOCAL_POPS_CONTROLLABLE while 112 (the first one after those included in the struct) corresponds to LOCAL_POPS_PRODUCE_HEROES. I came to these conclusions by looking at TOAD_MAN while modifying the c_variation_default.txt [CREATURE_VARIATION:ANIMAL_PERSON], generating worlds, and looking at the corresponding raw state info. Removing the two tags above toggled both of the flags to False, while removing them one at a time caused one of them to toggle, as per the conclusion above.
Edit: I believe unk_49 is "civilized" as the list contains all the civ building races. Dwarf, Human, Elf, Goblin, Kobold, Cave_Fish_Man, Olm_Man, Bat_Man, Cave_Swallow_Man, Amphibian_Man, Reptile_Man, Serpent_Man, Ant_Man, and Rodent_Man.
creature.flags [116] is set only on CASTE_CAN_LEARN creatures, but I can't figure out what aspect it is tied to: Blind Cave Ogre, Manera, Troll, Ogre, Giant, Blizzard Man, Troglodyte, and some, but not all, Night Creatures. Note that only the regular Giant is included, but not the Ettin, for instance.
Edit 2: Running a script over all creatures printing all creatures that have the raw string "[SLOW_LEARNER]" and printing all creature that have flag 116 set shows a perfect match.
The script used to match tags with flags:
function strip (str)
local i = string.find (str, ":")
if not i then
return str
end
return string.sub (str, 1, i - 1) .. "]"
end
function match_creature_raw_flags ()
local raw_set = {}
local flags = {}
for i, flag in ipairs (df.global.world.raws.creatures.all [0].flags) do
flags [i] = flag
end
for i, creature in ipairs (df.global.world.raws.creatures.all) do
for k, flag in ipairs (creature.flags) do
if flags [k] ~= creature.flags [k] then
flags [k] = -1
end
end
for k, str in ipairs (creature.raws) do
local token = strip (str [0])
if raw_set [token] then
raw_set [token] ["count"] = raw_set [token] ["count"] + 1
else
raw_set [token] = {["count"] = 1, ["flags"] = {}}
for l, flag in ipairs (creature.flags) do
raw_set [token] ["flags"] [l] = {["present"] = -1, ["absent"] = -1}
end
end
end
end
for i, creature in ipairs (df.global.world.raws.creatures.all) do
dfhack.println (creature.creature_id)
local matched = {}
for k, str in ipairs (creature.raws) do
local token = strip (str [0])
matched [token] = true
for l, flag in ipairs (creature.flags) do
if raw_set [token] ["flags"] [l] ["present"] == -1 then
raw_set [token] ["flags"] [l] ["present"] = flag
elseif raw_set [token] ["flags"] [l] ["present"] ~= flag then
raw_set [token] ["flags"] [l] ["present"] = 2 -- Redundant assignment when already mismatch
end
end
end
for k, raw in pairs (raw_set) do
if not matched [k] then
for l, flag in ipairs (creature.flags) do
if raw_set [k] ["flags"] [l] ["absent"] == -1 then
raw_set [k] ["flags"] [l] ["absent"] = flag
elseif raw_set [k] ["flags"] [l] ["absent"] ~= flag then
raw_set [k] ["flags"] [l] ["absent"] = 2 -- Redundant assignment when already mismatch
end
end
end
end
end
for i, flag in ipairs (df.global.world.raws.creatures.all [0].flags) do
if flags [i] == -1 then -- Skip flags that do not change.
dfhack.println ("Flag:", i, df.creature_raw_flags [i])
for k, raw in pairs (raw_set) do
if (raw ["flags"] [i] ["present"] == true or
raw ["flags"] [i] ["present"] == false) and
(raw ["flags"] [i] ["absent"] == true or
raw ["flags"] [i] ["absent"] == false) and
raw ["flags"] [i] ["present"] ~= raw ["flags"] [i] ["absent"] then
dfhack.println ("", k, raw ["flags"] [i] ["present"])
end
end
end
end
end
match_creature_raw_flags ()